GCC Code Coverage Report


Directory: ./
File: storage/innobase/handler/ha_innodb.cc
Date: 2022-11-26 14:12:44
Exec Total Coverage
Lines: 8306 9541 87.1%
Branches: 7914 13395 59.1%

Line Branch Exec Source
1 /*****************************************************************************
2
3 Copyright (c) 2000, 2022, Oracle and/or its affiliates.
4 Copyright (c) 2008, 2009 Google Inc.
5 Copyright (c) 2009, Percona Inc.
6 Copyright (c) 2012, Facebook Inc.
7
8 Portions of this file contain modifications contributed and copyrighted by
9 Google, Inc. Those modifications are gratefully acknowledged and are described
10 briefly in the InnoDB documentation. The contributions by Google are
11 incorporated with their permission, and subject to the conditions contained in
12 the file COPYING.Google.
13
14 Portions of this file contain modifications contributed and copyrighted
15 by Percona Inc.. Those modifications are
16 gratefully acknowledged and are described briefly in the InnoDB
17 documentation. The contributions by Percona Inc. are incorporated with
18 their permission, and subject to the conditions contained in the file
19 COPYING.Percona.
20
21 This program is free software; you can redistribute it and/or modify it under
22 the terms of the GNU General Public License, version 2.0, as published by the
23 Free Software Foundation.
24
25 This program is also distributed with certain software (including but not
26 limited to OpenSSL) that is licensed under separate terms, as designated in a
27 particular file or component or in included license documentation. The authors
28 of MySQL hereby grant you an additional permission to link the program and
29 your derivative works with the separately licensed software that they have
30 included with MySQL.
31
32 This program is distributed in the hope that it will be useful, but WITHOUT
33 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
35 for more details.
36
37 You should have received a copy of the GNU General Public License along with
38 this program; if not, write to the Free Software Foundation, Inc.,
39 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
40
41 *****************************************************************************/
42
43 /** @file ha_innodb.cc */
44
45 #ifndef UNIV_HOTBACKUP
46 #include "my_config.h"
47 #endif /* !UNIV_HOTBACKUP */
48
49 #include <auto_thd.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <gstream.h>
53 #include <limits.h>
54 #include <log.h>
55 #include <math.h>
56 #include <my_compare.h>
57 #include <mysqld.h>
58 #include <stdlib.h>
59 #include <strfunc.h>
60 #include <time.h>
61
62 #include <algorithm>
63
64 #include <sql_table.h>
65 #include "mysql/components/services/system_variable_source.h"
66
67 #ifndef UNIV_HOTBACKUP
68 #include <current_thd.h>
69 #include <debug_sync.h>
70 #include <derror.h>
71 #include <my_bitmap.h>
72 #include <my_check_opt.h>
73 #include <mysql/service_thd_alloc.h>
74 #include <mysql/service_thd_wait.h>
75 #include <mysql_com.h>
76 #include <sql_acl.h>
77 #include <sql_class.h>
78 #include <sql_show.h>
79 #include <sql_tablespace.h>
80 #include <sql_thd_internal_api.h>
81 #include <sys_vars_shared.h>
82 #include "api0api.h"
83 #include "api0misc.h"
84 #include "arch0arch.h"
85 #include "arch0page.h"
86 #include "auth_acls.h"
87 #include "btr0btr.h"
88 #include "btr0cur.h"
89 #include "btr0sea.h"
90 #include "buf0dblwr.h"
91 #include "buf0dump.h"
92 #include "buf0flu.h"
93 #include "buf0lru.h"
94 #include "buf0stats.h"
95 #include "clone0api.h"
96 #include "clone0clone.h"
97 #include "dd/dd.h"
98 #include "dd/dictionary.h"
99 #include "dd/impl/bootstrap/bootstrap_ctx.h"
100 #include "dd/properties.h"
101 #include "dd/types/index.h"
102 #include "dd/types/object_table.h"
103 #include "dd/types/object_table_definition.h"
104 #include "dd/types/partition.h"
105 #include "dd/types/table.h"
106 #include "dd/types/tablespace.h"
107 #include "ddl0ddl.h"
108 #include "dict0boot.h"
109 #include "dict0crea.h"
110 #include "dict0dd.h"
111 #include "dict0dict.h"
112 #include "dict0load.h"
113 #include "dict0stats.h"
114 #include "dict0stats_bg.h"
115 #include "fil0crypt.h"
116 #include "fil0fil.h"
117 #include "fsp0fsp.h"
118 #include "fsp0space.h"
119 #include "fsp0sysspace.h"
120 #include "fts0fts.h"
121 #include "fts0plugin.h"
122 #include "fts0priv.h"
123 #include "fts0tokenize.h" // true_word_char
124 #include "fts0types.h"
125 #include "ha_innodb.h"
126 #include "ha_innopart.h"
127 #include "ha_prototypes.h"
128 #include "i_s.h"
129 #include "ibuf0ibuf.h"
130 #include "lex_string.h"
131 #include "lob0lob.h"
132 #include "lock0lock.h"
133 #include "log0buf.h"
134 #include "log0chkp.h"
135 #include "log0encryption.h"
136 #include "log0meb.h"
137 #include "log0pfs.h"
138 #include "log0pre_8_0_30.h"
139 #include "log0write.h"
140 #include "mem0mem.h"
141 #include "mtr0mtr.h"
142 #include "my_compare.h"
143 #include "my_compiler.h"
144 #include "my_dbug.h"
145 #include "my_double2ulonglong.h"
146 #include "my_io.h"
147 #include "my_macros.h"
148 #include "my_psi_config.h"
149 #include "mysql/components/services/log_builtins.h"
150 #include "mysql/plugin.h"
151 #include "mysql/psi/mysql_data_lock.h"
152 #include "mysys_err.h"
153 #include "os0thread-create.h"
154 #include "os0thread.h"
155 #include "p_s.h"
156 #include "page0zip.h"
157 #include "pars0pars.h"
158 #include "rem0types.h"
159 #include "row0ext.h"
160 #include "row0import.h"
161 #include "row0ins.h"
162 #include "row0mysql.h"
163 #include "row0quiesce.h"
164 #include "row0sel.h"
165 #include "row0upd.h"
166 #include "sql/plugin_table.h"
167 #include "srv0mon.h"
168 #include "srv0srv.h"
169 #include "srv0start.h"
170 #include "sync0sync.h"
171 #ifdef UNIV_DEBUG
172 #include "trx0purge.h"
173 #endif /* UNIV_DEBUG */
174 #include "dict0priv.h"
175 #include "dict0sdi.h"
176 #include "dict0upgrade.h"
177 #include "os0thread-create.h"
178 #include "os0thread.h"
179 #include "sql/auth/auth_common.h"
180 #include "sql/item.h"
181 #include "sql_base.h"
182 #include "srv0tmp.h"
183 #include "trx0rec.h"
184 #include "trx0roll.h"
185 #include "trx0rseg.h"
186 #include "trx0sys.h"
187 #include "trx0trx.h"
188 #include "trx0xa.h"
189 #include "ut0mem.h"
190 #include "ut0test.h"
191 #include "xtradb_i_s.h"
192 #else
193 #include <typelib.h>
194 #include "buf0types.h"
195 #include "univ.i"
196 #endif /* !UNIV_HOTBACKUP */
197
198 #include "log0files_io.h"
199
200 #include "sql-common/json_binary.h"
201 #include "sql-common/json_dom.h"
202
203 #include "os0enc.h"
204 #include "os0file.h"
205
206 #include <mutex>
207 #include <sstream>
208 #include <string>
209 #include <vector>
210
211 #ifdef HAVE_UNISTD_H
212 #include <unistd.h>
213 #endif /* HAVE_UNISTD_H */
214
215 #ifndef UNIV_HOTBACKUP
216
217 namespace innobase {
218 namespace component_services {
219 SERVICE_TYPE(registry) *reg_srv = nullptr;
220
221 /** Initialize component service handles */
222 12027 static bool intitialize_service_handles() {
223
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 DBUG_TRACE;
224
225 auto cleanup = [&]() {
226 /* Add module specific deinitialization here */
227 innobase::encryption::deinit_keyring_services(reg_srv);
228 mysql_plugin_registry_release(reg_srv);
229 };
230
231
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 reg_srv = mysql_plugin_registry_acquire();
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 if (reg_srv == nullptr) {
233 return false;
234 }
235
236 /* Add module specific initialization here */
237
2/4
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
12027 if (innobase::encryption::init_keyring_services(reg_srv) == false) {
238 cleanup();
239 return false;
240 }
241
242 /* During initialize, PFS is not ready. */
243
3/4
✓ Branch 0 taken 11730 times.
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
23757 if (!opt_initialize &&
244
2/4
✓ Branch 0 taken 11730 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11730 times.
11730 !log_pfs_acquire_services(innobase::component_services::reg_srv)) {
245 ib::warn(ER_IB_MSG_LOG_PFS_ACQUIRE_SERVICES_FAILED);
246 }
247
248 12027 return true;
249 12027 }
250
251 /** Deinitialize compoent service handles */
252 10504 static void deinitialize_service_handles() {
253
1/2
✓ Branch 0 taken 10504 times.
✗ Branch 1 not taken.
10504 DBUG_TRACE;
254
2/2
✓ Branch 0 taken 10204 times.
✓ Branch 1 taken 300 times.
10504 if (!opt_initialize) {
255
1/2
✓ Branch 0 taken 10204 times.
✗ Branch 1 not taken.
10204 log_pfs_release_services(reg_srv);
256 }
257
1/2
✓ Branch 0 taken 10504 times.
✗ Branch 1 not taken.
10504 innobase::encryption::deinit_keyring_services(reg_srv);
258
2/2
✓ Branch 0 taken 10496 times.
✓ Branch 1 taken 8 times.
10504 if (reg_srv != nullptr) {
259
1/2
✓ Branch 0 taken 10496 times.
✗ Branch 1 not taken.
10496 mysql_plugin_registry_release(reg_srv);
260 }
261 10504 }
262
263 } // namespace component_services
264 } // namespace innobase
265
266 /** Stop printing warnings, if the count exceeds this threshold. */
267 static const size_t MOVED_FILES_PRINT_THRESHOLD = 32;
268
269 SERVICE_TYPE(registry) * reg_svc;
270 SERVICE_TYPE(system_variable_source) * sysvar_source_svc;
271 SERVICE_TYPE(clone_protocol) * clone_protocol_svc;
272
273 static const uint64_t KB = 1024;
274 static const uint64_t MB = KB * 1024;
275 static const uint64_t GB = MB * 1024;
276
277 /** fil_space_t::flags for hard-coded tablespaces */
278 uint32_t predefined_flags;
279
280 /** to protect innobase_open_files */
281 static mysql_mutex_t innobase_share_mutex;
282
283 /* mutex protecting the master_key_id change. */
284 ib_mutex_t master_key_id_mutex;
285
286 /** to force correct commit order in binlog */
287 static ulong commit_threads = 0;
288 static mysql_cond_t commit_cond;
289 static mysql_mutex_t commit_cond_m;
290 mysql_cond_t resume_encryption_cond;
291 mysql_mutex_t resume_encryption_cond_m;
292 bool innodb_inited = false;
293
294 3939808180 [[maybe_unused]] static inline bool EQ_CURRENT_THD(THD *thd) {
295 3939808180 return thd == current_thd;
296 }
297
298 static struct handlerton *innodb_hton_ptr;
299
300 static const long AUTOINC_OLD_STYLE_LOCKING = 0;
301 static const long AUTOINC_NEW_STYLE_LOCKING = 1;
302 static const long AUTOINC_NO_LOCKING = 2;
303
304 static long innobase_open_files;
305 static long innobase_autoinc_lock_mode;
306 static ulong innobase_commit_concurrency = 0;
307
308 /* Boolean @@innodb_buffer_pool_in_core_file. */
309 bool srv_buffer_pool_in_core_file = true;
310
311 /** Percentage of the buffer pool to reserve for 'old' blocks.
312 Connected to buf_LRU_old_ratio. */
313 static uint innobase_old_blocks_pct;
314
315 /* The default values for the following char* start-up parameters
316 are determined in innodb_init_params(). */
317
318 static char *innobase_data_home_dir = nullptr;
319 static char *innobase_data_file_path = nullptr;
320 static char *innobase_temp_data_file_path = nullptr;
321 static char *innobase_enable_monitor_counter = nullptr;
322 static char *innobase_disable_monitor_counter = nullptr;
323 static char *innobase_reset_monitor_counter = nullptr;
324 static char *innobase_reset_all_monitor_counter = nullptr;
325 static char *innobase_doublewrite_dir = nullptr;
326
327 static ulong innodb_flush_method;
328
329 /* This variable can be set in the server configure file, specifying
330 stopword table to be used */
331 static char *innobase_server_stopword_table = nullptr;
332
333 /* Below we have boolean-valued start-up parameters, and their default
334 values */
335
336 static bool innobase_rollback_on_timeout = false;
337 static bool innobase_create_status_file = false;
338 bool innobase_stats_on_metadata = true;
339 static bool innodb_optimize_fulltext_only = false;
340
341 static char *innodb_version_str = (char *)INNODB_VERSION_STR;
342
343 static Innodb_data_lock_inspector innodb_data_lock_inspector;
344
345 static const uint MAX_ENCRYPTION_THREADS = 255;
346 extern uint srv_fil_crypt_rotate_key_age;
347 extern uint srv_n_fil_crypt_iops;
348
349 /** Path to the Percona-specific parallel doublewrite buffer (Deprecated) */
350 static char *srv_parallel_doublewrite_path_deprecated = nullptr;
351
352 /** Enable or disable encryption of pages in parallel doublewrite buffer
353 file (Deprecated) */
354 static bool srv_parallel_dblwr_encrypt_deprecated = false;
355
356 /** Note we cannot use rec_format_enum because we do not allow
357 COMPRESSED row format for innodb_default_row_format option. */
358 enum default_row_format_enum {
359 DEFAULT_ROW_FORMAT_REDUNDANT = 0,
360 DEFAULT_ROW_FORMAT_COMPACT = 1,
361 DEFAULT_ROW_FORMAT_DYNAMIC = 2,
362 };
363
364 #if defined(_WIN32) || defined(_WIN64)
365 #include <Windows.h>
366 static double get_mem_GlobalMemoryStatus() {
367 MEMORYSTATUSEX ms;
368 ms.dwLength = sizeof(ms);
369 GlobalMemoryStatusEx(&ms);
370 return (((double)ms.ullTotalPhys) / GB);
371 }
372 #undef get_sys_mem
373 #define get_sys_mem get_mem_GlobalMemoryStatus
374 #else
375 static double get_mem_sysconf() {
376 return (((double)sysconf(_SC_PHYS_PAGES)) *
377 ((double)sysconf(_SC_PAGESIZE) / GB));
378 }
379 #undef get_sys_mem
380 #define get_sys_mem get_mem_sysconf
381 #endif /* defined(_WIN32) || defined(_WIN64) */
382
383 /** Release all acquired services from mysql server. */
384 10504 static void release_plugin_services() {
385
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 10417 times.
10504 if (reg_svc == nullptr) {
386 87 return;
387 }
388
389
1/2
✓ Branch 0 taken 10417 times.
✗ Branch 1 not taken.
10417 if (sysvar_source_svc != nullptr) {
390 using sysvar_source_svc_t = SERVICE_TYPE_NO_CONST(system_variable_source);
391 10417 reg_svc->release(reinterpret_cast<my_h_service>(
392 const_cast<sysvar_source_svc_t *>(sysvar_source_svc)));
393 10417 sysvar_source_svc = nullptr;
394 }
395
396
1/2
✓ Branch 0 taken 10417 times.
✗ Branch 1 not taken.
10417 if (clone_protocol_svc != nullptr) {
397 using clone_protocol_t = SERVICE_TYPE_NO_CONST(clone_protocol);
398 10417 reg_svc->release(reinterpret_cast<my_h_service>(
399 const_cast<clone_protocol_t *>(clone_protocol_svc)));
400 10417 clone_protocol_svc = nullptr;
401 }
402
403 /* Release registry service */
404 10417 mysql_plugin_registry_release(reg_svc);
405 10417 reg_svc = nullptr;
406 }
407
408 /** Acquire required services from mysql server. */
409 12035 static void acquire_plugin_services() {
410 /* Acquire mysql_server's registry service */
411
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 reg_svc = mysql_plugin_registry_acquire();
412
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12035 times.
12035 if (reg_svc == nullptr) {
414 ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "plugin registry");
415 return;
416 }
417
418 my_h_service service;
419
420 /* Acquire system_variable_source service */
421
2/4
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12035 times.
12035 if (reg_svc->acquire("system_variable_source", &service)) {
422 ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "system_variable_source");
423
424 } else {
425 12035 sysvar_source_svc =
426 reinterpret_cast<SERVICE_TYPE(system_variable_source) *>(service);
427 }
428
429 /* Acquire clone protocol service handle. */
430
2/4
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12035 times.
12035 if (reg_svc->acquire("clone_protocol", &service)) {
431 ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "clone_protocol");
432
433 } else {
434 12035 clone_protocol_svc =
435 reinterpret_cast<SERVICE_TYPE(clone_protocol) *>(service);
436 }
437 }
438
439 /** Return the InnoDB ROW_FORMAT enum value
440 @param[in] row_format row_format from "innodb_default_row_format"
441 @return InnoDB ROW_FORMAT value from rec_format_t enum. */
442 428400 static rec_format_t get_row_format(ulong row_format) {
443
3/4
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 227 times.
✓ Branch 2 taken 428052 times.
✗ Branch 3 not taken.
428400 switch (row_format) {
444 121 case DEFAULT_ROW_FORMAT_REDUNDANT:
445 121 return (REC_FORMAT_REDUNDANT);
446 227 case DEFAULT_ROW_FORMAT_COMPACT:
447 227 return (REC_FORMAT_COMPACT);
448 428052 case DEFAULT_ROW_FORMAT_DYNAMIC:
449 428052 return (REC_FORMAT_DYNAMIC);
450 default:
451 ut_d(ut_error);
452 ut_o(return (REC_FORMAT_DYNAMIC));
453 }
454 }
455
456 /** Note that a transaction has been deregistered.
457 @param[in] trx transaction */
458 static void trx_deregister_from_2pc(trx_t *trx);
459 static ulong innodb_default_row_format = DEFAULT_ROW_FORMAT_DYNAMIC;
460
461 #ifdef UNIV_DEBUG
462 /** Values for --innodb-debug-compress names. */
463 static const char *innodb_debug_compress_names[] = {"none", "zlib", "lz4",
464 "lz4hc", NullS};
465
466 /** Enumeration of --innodb-debug-compress */
467 static TYPELIB innodb_debug_compress_typelib = {
468 array_elements(innodb_debug_compress_names) - 1,
469 "innodb_debug_compress_typelib", innodb_debug_compress_names, nullptr};
470 #endif /* UNIV_DEBUG */
471
472 /** Possible values for system variable "innodb_stats_method". The values
473 are defined the same as its corresponding MyISAM system variable
474 "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
475 static const char *innodb_stats_method_names[] = {
476 "nulls_equal", "nulls_unequal", "nulls_ignored", NullS};
477
478 /** Used to define an enumerate type of the system variable innodb_stats_method.
479 This is the same as "myisam_stats_method_typelib" */
480 static TYPELIB innodb_stats_method_typelib = {
481 array_elements(innodb_stats_method_names) - 1,
482 "innodb_stats_method_typelib", innodb_stats_method_names, nullptr};
483
484 #endif /* UNIV_HOTBACKUP */
485
486 /** Possible values of the parameter innodb_checksum_algorithm */
487 static const char *innodb_checksum_algorithm_names[] = {
488 "crc32", "strict_crc32", "innodb", "strict_innodb",
489 "none", "strict_none", NullS};
490
491 /** Used to define an enumerate type of the system variable
492 innodb_checksum_algorithm. */
493 static TYPELIB innodb_checksum_algorithm_typelib = {
494 array_elements(innodb_checksum_algorithm_names) - 1,
495 "innodb_checksum_algorithm_typelib", innodb_checksum_algorithm_names,
496 nullptr};
497
498 #ifndef UNIV_HOTBACKUP
499 /** Names of allowed values of innodb_flush_method */
500 static const char *innodb_flush_method_names[] = {
501 #ifndef _WIN32 /* See srv_unix_flush_t */
502 "fsync", "O_DSYNC", "littlesync", "nosync", "O_DIRECT", "O_DIRECT_NO_FSYNC",
503 #else /* _WIN32; see srv_win_flush_t */
504 "unbuffered", "normal",
505 #endif
506 NullS};
507
508 /** Enumeration of innodb_flush_method */
509 static TYPELIB innodb_flush_method_typelib = {
510 array_elements(innodb_flush_method_names) - 1,
511 "innodb_flush_method_typelib", innodb_flush_method_names, nullptr};
512
513 /** Possible values for system variable "innodb_cleaner_lsn_age_factor". */
514 static const char *innodb_cleaner_lsn_age_factor_names[] = {
515 "legacy", "high_checkpoint", NullS};
516
517 /** Enumeration for innodb_cleaner_lsn_age_factor. */
518 static TYPELIB innodb_cleaner_lsn_age_factor_typelib = {
519 array_elements(innodb_cleaner_lsn_age_factor_names) - 1,
520 "innodb_cleaner_lsn_age_factor_typelib",
521 innodb_cleaner_lsn_age_factor_names, nullptr};
522
523 /** Possible values for system variable "innodb_empty_free_list_algorithm". */
524 static const char *innodb_empty_free_list_algorithm_names[] = {
525 "legacy", "backoff", NullS};
526
527 /** Enumeration for innodb_empty_free_list_algorithm. */
528 static TYPELIB innodb_empty_free_list_algorithm_typelib = {
529 array_elements(innodb_empty_free_list_algorithm_names) - 1,
530 "innodb_empty_free_list_algorithm_typelib",
531 innodb_empty_free_list_algorithm_names, nullptr};
532
533 /** Possible values for system variable "innodb_default_row_format". */
534 static const char *innodb_default_row_format_names[] = {"redundant", "compact",
535 "dynamic", NullS};
536
537 /** Used to define an enumerate type of the system variable
538 innodb_default_row_format. */
539 static TYPELIB innodb_default_row_format_typelib = {
540 array_elements(innodb_default_row_format_names) - 1,
541 "innodb_default_row_format_typelib", innodb_default_row_format_names,
542 nullptr};
543
544 /** Possible values for system variable "innodb_doublewrite".
545 @note: If you change order or add new values, please update dblwr::mode_t. */
546 static const char *innodb_doublewrite_names[] = {
547 "OFF", "ON", "DETECT_ONLY", "DETECT_AND_RECOVER", "FALSE", "TRUE", NullS};
548
549 /** Used to define an enumerate type of the system variable
550 innodb_default_row_format. */
551 static TYPELIB innodb_doublewrite_typelib = {
552 array_elements(innodb_doublewrite_names) - 1, "innodb_doublewrite_typelib",
553 innodb_doublewrite_names, nullptr};
554
555 #else /* !UNIV_HOTBACKUP */
556
557 /** Returns the name of the checksum algorithm corresponding to the
558 algorithm id given by "algo_enum" parameter.
559 @param[in] algo_enum algorithm enumerator
560 @return C-string algorithm name */
561 const char *meb_get_checksum_algorithm_name(
562 srv_checksum_algorithm_t algo_enum) {
563 return (get_type(&innodb_checksum_algorithm_typelib, algo_enum));
564 }
565
566 /** Retrieves the enum corresponding to the checksum algorithm
567 name specified by algo_name. If the call succeeds, returns
568 true and checksum algorithm enum is returned in algo_enum.
569 @param[in] algo_name algorithm name
570 @param[out] algo_enum algorithm enumerator
571 @retval true if successful
572 @retval false if algorithn name not found */
573 bool meb_get_checksum_algorithm_enum(const char *algo_name,
574 srv_checksum_algorithm_t &algo_enum) {
575 int type =
576 find_type(algo_name, &innodb_checksum_algorithm_typelib, FIND_TYPE_BASIC);
577 if (type <= 0) {
578 /** Invalid algorithm name */
579 return false;
580 } else {
581 algo_enum = srv_checksum_algorithm_t(type - 1);
582 }
583
584 return true;
585 }
586 #endif /* !UNIV_HOTBACKUP */
587
588 static const char *sys_tablespace_encrypt_names[] = {
589 "OFF", "ON", "RE_ENCRYPTING_TO_KEYRING", NullS};
590 static TYPELIB sys_tablespace_encrypt_typelib = {
591 array_elements(sys_tablespace_encrypt_names) - 1,
592 "sys_tablespace_encrypt_typelib", sys_tablespace_encrypt_names, nullptr};
593
594 #ifndef UNIV_HOTBACKUP
595 /* The following counter is used to convey information to InnoDB
596 about server activity: in case of normal DML ops it is not
597 sensible to call srv_active_wake_master_thread after each
598 operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */
599
600 constexpr uint32_t INNOBASE_WAKE_INTERVAL = 32;
601 static ulong innobase_active_counter = 0;
602
603 static hash_table_t *innobase_open_tables;
604
605 /** Array of data files of the system tablespace */
606 static std::vector<Plugin_tablespace::Plugin_tablespace_file *,
607 ut::allocator<Plugin_tablespace::Plugin_tablespace_file *>>
608 innobase_sys_files;
609
610 /** Allowed values of innodb_change_buffering */
611 static const char *innodb_change_buffering_names[] = {
612 "none", /* IBUF_USE_NONE */
613 "inserts", /* IBUF_USE_INSERT */
614 "deletes", /* IBUF_USE_DELETE_MARK */
615 "changes", /* IBUF_USE_INSERT_DELETE_MARK */
616 "purges", /* IBUF_USE_DELETE */
617 "all", /* IBUF_USE_ALL */
618 NullS};
619
620 /** Enumeration of innodb_change_buffering */
621 static TYPELIB innodb_change_buffering_typelib = {
622 array_elements(innodb_change_buffering_names) - 1,
623 "innodb_change_buffering_typelib", innodb_change_buffering_names, nullptr};
624
625 /** Retrieve the FTS Relevance Ranking result for doc with doc_id
626 of m_prebuilt->fts_doc_id
627 @param[in,out] fts_hdl FTS handler
628 @return the relevance ranking value */
629 static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl);
630 /** Free the memory for the FTS handler
631 @param[in,out] fts_hdl FTS handler */
632 static void innobase_fts_close_ranking(FT_INFO *fts_hdl);
633
634 /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id
635 of m_prebuilt->fts_doc_id
636 @param[in,out] fts_hdl FTS handler
637 @return the relevance ranking value */
638 static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint);
639
640 /* Call back function array defined by MySQL and used to
641 retrieve FTS results. */
642 const struct _ft_vft ft_vft_result = {nullptr, innobase_fts_find_ranking,
643 innobase_fts_close_ranking,
644 innobase_fts_retrieve_ranking, nullptr};
645
646 /** @return version of the extended FTS API */
647 static uint innobase_fts_get_version() {
648 /* Currently this doesn't make much sense as returning
649 HA_CAN_FULLTEXT_EXT automatically mean this version is supported.
650 This supposed to ease future extensions. */
651 return (2);
652 }
653
654 /** @return Which part of the extended FTS API is supported */
655 169 static ulonglong innobase_fts_flags() {
656 169 return (FTS_ORDERED_RESULT | FTS_DOCID_IN_RESULT);
657 }
658
659 /** Find and Retrieve the FTS doc_id for the current result row
660 @param[in,out] fts_hdl FTS handler
661 @return the document ID */
662 static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl);
663
664 /** Find and retrieve the size of the current result
665 @param[in,out] fts_hdl FTS handler
666 @return number of matching rows */
667 152 static ulonglong innobase_fts_count_matches(
668 FT_INFO_EXT *fts_hdl) /*!< in: FTS handler */
669 {
670 152 NEW_FT_INFO *handle = reinterpret_cast<NEW_FT_INFO *>(fts_hdl);
671
672
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 15 times.
152 if (handle->ft_result->rankings_by_id != nullptr) {
673 137 return (rbt_size(handle->ft_result->rankings_by_id));
674 } else {
675 15 return (0);
676 }
677 }
678
679 const struct _ft_vft_ext ft_vft_ext_result = {
680 innobase_fts_get_version, innobase_fts_flags, innobase_fts_retrieve_docid,
681 innobase_fts_count_matches};
682
683 #ifdef HAVE_PSI_INTERFACE
684 #define PSI_KEY(n, flag, volatility, doc) \
685 { &(n##_key.m_value), #n, flag, volatility, doc }
686 #define PSI_MEMORY_KEY(n, flag, volatility, doc) \
687 { &(n##_key), #n, flag, volatility, doc }
688 #define PSI_MUTEX_KEY(n, flag, volatility, doc) \
689 { &(n##_key.m_value), #n, flag, volatility, doc }
690 /* All RWLOCK used in Innodb are SX-locks */
691 #define PSI_RWLOCK_KEY(n, volatility, doc) \
692 { &n##_key.m_value, #n, PSI_FLAG_RWLOCK_SX, volatility, doc }
693 #define PSI_THREAD_KEY(n, osn, flag, volatility, doc) \
694 { &(n##_key.m_value), #n, osn, flag, volatility, doc }
695
696 /* Keys to register pthread mutexes/cond in the current file with
697 performance schema */
698 static mysql_pfs_key_t innobase_share_mutex_key;
699 static mysql_pfs_key_t commit_cond_mutex_key;
700 static mysql_pfs_key_t commit_cond_key;
701 mysql_pfs_key_t resume_encryption_cond_mutex_key;
702 mysql_pfs_key_t resume_encryption_cond_key;
703
704 static PSI_mutex_info all_pthread_mutexes[] = {
705 PSI_MUTEX_KEY(commit_cond_mutex, 0, 0, PSI_DOCUMENT_ME),
706 PSI_MUTEX_KEY(innobase_share_mutex, 0, 0, PSI_DOCUMENT_ME),
707 PSI_MUTEX_KEY(resume_encryption_cond_mutex, 0, 0, PSI_DOCUMENT_ME)};
708
709 static PSI_cond_info all_innodb_conds[] = {
710 PSI_KEY(commit_cond, 0, 0, PSI_DOCUMENT_ME),
711 PSI_KEY(resume_encryption_cond, 0, 0, PSI_DOCUMENT_ME)};
712
713 #ifdef UNIV_PFS_MEMORY
714 /* pfs keys related to memory that is performance schema instrumented
715 when "UNIV_PFS_MEMORY" is defined */
716 static PSI_memory_info pfs_instrumented_innodb_memory[] = {
717 PSI_MEMORY_KEY(log_buffer_memory, 0, 0, "Redo log buffer")};
718 #endif /* UNIV_PFS_MEMORY */
719
720 #ifdef UNIV_PFS_MUTEX
721 /* all_innodb_mutexes array contains mutexes that are
722 performance schema instrumented if "UNIV_PFS_MUTEX"
723 is defined */
724 static PSI_mutex_info all_innodb_mutexes[] = {
725 PSI_MUTEX_KEY(autoinc_mutex, 0, 0, PSI_DOCUMENT_ME),
726 PSI_MUTEX_KEY(autoinc_persisted_mutex, 0, 0, PSI_DOCUMENT_ME),
727 #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
728 PSI_MUTEX_KEY(buffer_block_mutex, 0, 0, PSI_DOCUMENT_ME),
729 #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
730 PSI_MUTEX_KEY(buf_pool_chunks_mutex, 0, 0, PSI_DOCUMENT_ME),
731 PSI_MUTEX_KEY(buf_pool_flush_state_mutex, 0, 0, PSI_DOCUMENT_ME),
732 PSI_MUTEX_KEY(buf_pool_LRU_list_mutex, 0, 0, PSI_DOCUMENT_ME),
733 PSI_MUTEX_KEY(buf_pool_free_list_mutex, 0, 0, PSI_DOCUMENT_ME),
734 PSI_MUTEX_KEY(buf_pool_zip_free_mutex, 0, 0, PSI_DOCUMENT_ME),
735 PSI_MUTEX_KEY(buf_pool_zip_hash_mutex, 0, 0, PSI_DOCUMENT_ME),
736 PSI_MUTEX_KEY(buf_pool_zip_mutex, 0, 0, PSI_DOCUMENT_ME),
737 PSI_MUTEX_KEY(clone_snapshot_mutex, 0, 0, PSI_DOCUMENT_ME),
738 PSI_MUTEX_KEY(clone_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
739 PSI_MUTEX_KEY(clone_task_mutex, 0, 0, PSI_DOCUMENT_ME),
740 PSI_MUTEX_KEY(ddl_autoinc_mutex, 0, 0, PSI_DOCUMENT_ME),
741 PSI_MUTEX_KEY(dict_foreign_err_mutex, 0, 0, PSI_DOCUMENT_ME),
742 PSI_MUTEX_KEY(dict_persist_dirty_tables_mutex, 0, 0, PSI_DOCUMENT_ME),
743 PSI_MUTEX_KEY(dict_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
744 PSI_MUTEX_KEY(dict_table_mutex, 0, 0, PSI_DOCUMENT_ME),
745 PSI_MUTEX_KEY(parser_mutex, 0, 0, PSI_DOCUMENT_ME),
746 PSI_MUTEX_KEY(recalc_pool_mutex, 0, 0, PSI_DOCUMENT_ME),
747 PSI_MUTEX_KEY(fil_system_mutex, 0, 0, PSI_DOCUMENT_ME),
748 PSI_MUTEX_KEY(file_open_mutex, 0, 0, PSI_DOCUMENT_ME),
749 PSI_MUTEX_KEY(flush_list_mutex, 0, 0, PSI_DOCUMENT_ME),
750 PSI_MUTEX_KEY(fts_bg_threads_mutex, 0, 0, PSI_DOCUMENT_ME),
751 PSI_MUTEX_KEY(fts_delete_mutex, 0, 0, PSI_DOCUMENT_ME),
752 PSI_MUTEX_KEY(fts_optimize_mutex, 0, 0, PSI_DOCUMENT_ME),
753 PSI_MUTEX_KEY(fts_doc_id_mutex, 0, 0, PSI_DOCUMENT_ME),
754 PSI_MUTEX_KEY(fts_pll_tokenize_mutex, 0, 0, PSI_DOCUMENT_ME),
755 PSI_MUTEX_KEY(hash_table_mutex, 0, 0, PSI_DOCUMENT_ME),
756 PSI_MUTEX_KEY(ibuf_bitmap_mutex, 0, 0, PSI_DOCUMENT_ME),
757 PSI_MUTEX_KEY(ibuf_mutex, 0, 0, PSI_DOCUMENT_ME),
758 PSI_MUTEX_KEY(ibuf_pessimistic_insert_mutex, 0, 0, PSI_DOCUMENT_ME),
759 PSI_MUTEX_KEY(lock_free_hash_mutex, 0, 0, PSI_DOCUMENT_ME),
760 PSI_MUTEX_KEY(log_limits_mutex, 0, 0, PSI_DOCUMENT_ME),
761 PSI_MUTEX_KEY(log_files_mutex, 0, 0, PSI_DOCUMENT_ME),
762 PSI_MUTEX_KEY(log_checkpointer_mutex, 0, 0, PSI_DOCUMENT_ME),
763 PSI_MUTEX_KEY(log_closer_mutex, 0, 0, PSI_DOCUMENT_ME),
764 PSI_MUTEX_KEY(log_writer_mutex, 0, 0, PSI_DOCUMENT_ME),
765 PSI_MUTEX_KEY(log_flusher_mutex, 0, 0, PSI_DOCUMENT_ME),
766 PSI_MUTEX_KEY(log_write_notifier_mutex, 0, 0, PSI_DOCUMENT_ME),
767 PSI_MUTEX_KEY(log_flush_notifier_mutex, 0, 0, PSI_DOCUMENT_ME),
768 PSI_MUTEX_KEY(log_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME),
769 PSI_MUTEX_KEY(log_cmdq_mutex, 0, 0, PSI_DOCUMENT_ME),
770 PSI_MUTEX_KEY(log_sn_mutex, 0, 0, PSI_DOCUMENT_ME),
771 PSI_MUTEX_KEY(mutex_list_mutex, 0, 0, PSI_DOCUMENT_ME),
772 PSI_MUTEX_KEY(page_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME),
773 PSI_MUTEX_KEY(page_sys_arch_oper_mutex, 0, 0, PSI_DOCUMENT_ME),
774 PSI_MUTEX_KEY(page_sys_arch_client_mutex, 0, 0, PSI_DOCUMENT_ME),
775 PSI_MUTEX_KEY(page_zip_stat_per_index_mutex, 0, 0, PSI_DOCUMENT_ME),
776 PSI_MUTEX_KEY(page_cleaner_mutex, 0, 0, PSI_DOCUMENT_ME),
777 PSI_MUTEX_KEY(parallel_read_mutex, 0, 0, PSI_DOCUMENT_ME),
778 PSI_MUTEX_KEY(dblwr_mutex, 0, 0, PSI_DOCUMENT_ME),
779 PSI_MUTEX_KEY(purge_sys_pq_mutex, 0, 0, PSI_DOCUMENT_ME),
780 PSI_MUTEX_KEY(recv_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
781 PSI_MUTEX_KEY(recv_writer_mutex, 0, 0, PSI_DOCUMENT_ME),
782 PSI_MUTEX_KEY(temp_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME),
783 PSI_MUTEX_KEY(undo_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME),
784 PSI_MUTEX_KEY(trx_sys_rseg_mutex, 0, 0, PSI_DOCUMENT_ME),
785 #ifdef UNIV_DEBUG
786 PSI_MUTEX_KEY(rw_lock_debug_mutex, 0, 0, PSI_DOCUMENT_ME),
787 #endif /* UNIV_DEBUG */
788 PSI_MUTEX_KEY(rw_lock_list_mutex, 0, 0, PSI_DOCUMENT_ME),
789 PSI_MUTEX_KEY(rw_lock_mutex, 0, 0, PSI_DOCUMENT_ME),
790 PSI_MUTEX_KEY(srv_innodb_monitor_mutex, 0, 0, PSI_DOCUMENT_ME),
791 PSI_MUTEX_KEY(srv_misc_tmpfile_mutex, 0, 0, PSI_DOCUMENT_ME),
792 PSI_MUTEX_KEY(srv_monitor_file_mutex, 0, 0, PSI_DOCUMENT_ME),
793 #ifdef UNIV_DEBUG
794 PSI_MUTEX_KEY(sync_thread_mutex, 0, 0, PSI_DOCUMENT_ME),
795 #endif /* UNIV_DEBUG */
796 PSI_MUTEX_KEY(trx_undo_mutex, 0, 0, PSI_DOCUMENT_ME),
797 PSI_MUTEX_KEY(trx_pool_mutex, 0, 0, PSI_DOCUMENT_ME),
798 PSI_MUTEX_KEY(trx_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME),
799 PSI_MUTEX_KEY(temp_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME),
800 PSI_MUTEX_KEY(srv_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
801 PSI_MUTEX_KEY(lock_sys_page_mutex, 0, 0, PSI_DOCUMENT_ME),
802 PSI_MUTEX_KEY(lock_sys_table_mutex, 0, 0, PSI_DOCUMENT_ME),
803 PSI_MUTEX_KEY(lock_wait_mutex, 0, 0, PSI_DOCUMENT_ME),
804 PSI_MUTEX_KEY(trx_mutex, 0, 0, PSI_DOCUMENT_ME),
805 PSI_MUTEX_KEY(srv_threads_mutex, 0, 0, PSI_DOCUMENT_ME),
806 #ifndef PFS_SKIP_EVENT_MUTEX
807 PSI_MUTEX_KEY(event_mutex, 0, 0, PSI_DOCUMENT_ME),
808 PSI_MUTEX_KEY(event_manager_mutex, 0, 0, PSI_DOCUMENT_ME),
809 #endif /* PFS_SKIP_EVENT_MUTEX */
810 PSI_MUTEX_KEY(rtr_active_mutex, 0, 0, PSI_DOCUMENT_ME),
811 PSI_MUTEX_KEY(rtr_match_mutex, 0, 0, PSI_DOCUMENT_ME),
812 PSI_MUTEX_KEY(rtr_path_mutex, 0, 0, PSI_DOCUMENT_ME),
813 PSI_MUTEX_KEY(rtr_ssn_mutex, 0, 0, PSI_DOCUMENT_ME),
814 PSI_MUTEX_KEY(trx_sys_mutex, 0, 0, PSI_DOCUMENT_ME),
815 PSI_MUTEX_KEY(trx_sys_shard_mutex, 0, 0, PSI_DOCUMENT_ME),
816 PSI_MUTEX_KEY(trx_sys_serialisation_mutex, 0, 0, PSI_DOCUMENT_ME),
817 PSI_MUTEX_KEY(zip_pad_mutex, 0, 0, PSI_DOCUMENT_ME),
818 PSI_MUTEX_KEY(master_key_id_mutex, 0, 0, PSI_DOCUMENT_ME),
819 PSI_MUTEX_KEY(sync_array_mutex, 0, 0, PSI_DOCUMENT_ME),
820 PSI_MUTEX_KEY(row_drop_list_mutex, 0, 0, PSI_DOCUMENT_ME)};
821 #endif /* UNIV_PFS_MUTEX */
822
823 #ifdef UNIV_PFS_RWLOCK
824 /* all_innodb_rwlocks array contains rwlocks that are
825 performance schema instrumented if "UNIV_PFS_RWLOCK"
826 is defined */
827 static PSI_rwlock_info all_innodb_rwlocks[] = {
828 PSI_RWLOCK_KEY(btr_search_latch, 0, PSI_DOCUMENT_ME),
829 #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
830 PSI_RWLOCK_KEY(buf_block_lock, 0, PSI_DOCUMENT_ME),
831 #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
832 #ifdef UNIV_DEBUG
833 PSI_RWLOCK_KEY(buf_block_debug_latch, 0, PSI_DOCUMENT_ME),
834 #endif /* UNIV_DEBUG */
835 PSI_RWLOCK_KEY(dict_operation_lock, 0, PSI_DOCUMENT_ME),
836 PSI_RWLOCK_KEY(fil_space_latch, 0, PSI_DOCUMENT_ME),
837 PSI_RWLOCK_KEY(log_sn_lock, 0, PSI_DOCUMENT_ME),
838 PSI_RWLOCK_KEY(undo_spaces_lock, 0, PSI_DOCUMENT_ME),
839 PSI_RWLOCK_KEY(rsegs_lock, 0, PSI_DOCUMENT_ME),
840 PSI_RWLOCK_KEY(lock_sys_global_rw_lock, 0, PSI_DOCUMENT_ME),
841 PSI_RWLOCK_KEY(fts_cache_rw_lock, 0, PSI_DOCUMENT_ME),
842 PSI_RWLOCK_KEY(fts_cache_init_rw_lock, 0, PSI_DOCUMENT_ME),
843 PSI_RWLOCK_KEY(trx_i_s_cache_lock, 0, PSI_DOCUMENT_ME),
844 PSI_RWLOCK_KEY(trx_purge_latch, 0, PSI_DOCUMENT_ME),
845 PSI_RWLOCK_KEY(index_tree_rw_lock, 0, PSI_DOCUMENT_ME),
846 PSI_RWLOCK_KEY(index_online_log, 0, PSI_DOCUMENT_ME),
847 PSI_RWLOCK_KEY(dict_table_stats, 0, PSI_DOCUMENT_ME),
848 PSI_RWLOCK_KEY(hash_table_locks, 0, PSI_DOCUMENT_ME),
849 };
850 #endif /* UNIV_PFS_RWLOCK */
851
852 #ifdef UNIV_PFS_THREAD
853 /* all_innodb_threads array contains threads that are
854 performance schema instrumented if "UNIV_PFS_THREAD"
855 is defined */
856 static PSI_thread_info all_innodb_threads[] = {
857 PSI_THREAD_KEY(log_archiver_thread, "ib_log_arch", PSI_FLAG_SINGLETON, 0,
858 PSI_DOCUMENT_ME),
859 PSI_THREAD_KEY(page_archiver_thread, "ib_page_arch", PSI_FLAG_SINGLETON, 0,
860 PSI_DOCUMENT_ME),
861 PSI_THREAD_KEY(buf_dump_thread, "ib_buf_dump", PSI_FLAG_SINGLETON, 0,
862 PSI_DOCUMENT_ME),
863 PSI_THREAD_KEY(clone_ddl_thread, "ib_clone_ddl", PSI_FLAG_SINGLETON, 0,
864 PSI_DOCUMENT_ME),
865 PSI_THREAD_KEY(clone_gtid_thread, "ib_clone_gtid", PSI_FLAG_SINGLETON, 0,
866 PSI_DOCUMENT_ME),
867 PSI_THREAD_KEY(ddl_thread, "ib_ddl", 0, 0, PSI_DOCUMENT_ME),
868 PSI_THREAD_KEY(dict_stats_thread, "ib_dict_stats", PSI_FLAG_SINGLETON, 0,
869 PSI_DOCUMENT_ME),
870 PSI_THREAD_KEY(io_handler_thread, "ib_io_handler", PSI_FLAG_SINGLETON, 0,
871 PSI_DOCUMENT_ME),
872 PSI_THREAD_KEY(io_ibuf_thread, "ib_io_ibuf", PSI_FLAG_SINGLETON, 0,
873 PSI_DOCUMENT_ME),
874 PSI_THREAD_KEY(io_log_thread, "ib_io_log", PSI_FLAG_SINGLETON, 0,
875 PSI_DOCUMENT_ME),
876 PSI_THREAD_KEY(io_read_thread, "ib_io_rd", 0, 0, PSI_DOCUMENT_ME),
877 PSI_THREAD_KEY(io_write_thread, "ib_io_wr", 0, 0, PSI_DOCUMENT_ME),
878 PSI_THREAD_KEY(buf_resize_thread, "ib_buf_resize", PSI_FLAG_SINGLETON, 0,
879 PSI_DOCUMENT_ME),
880 PSI_THREAD_KEY(log_files_governor_thread, "ib_log_files_g",
881 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
882 PSI_THREAD_KEY(log_writer_thread, "ib_log_writer", PSI_FLAG_SINGLETON, 0,
883 PSI_DOCUMENT_ME),
884 PSI_THREAD_KEY(log_checkpointer_thread, "ib_log_checkpt",
885 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
886 PSI_THREAD_KEY(log_flusher_thread, "ib_log_flush", PSI_FLAG_SINGLETON, 0,
887 PSI_DOCUMENT_ME),
888 PSI_THREAD_KEY(log_write_notifier_thread, "ib_log_wr_notif",
889 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
890 PSI_THREAD_KEY(log_flush_notifier_thread, "ib_log_fl_notif",
891 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
892 PSI_THREAD_KEY(buf_lru_manager_thread, "ib_buf_lru", 0, 0,
893 PSI_DOCUMENT_ME),
894 PSI_THREAD_KEY(recv_writer_thread, "ib_recv_write", PSI_FLAG_SINGLETON, 0,
895 PSI_DOCUMENT_ME),
896 PSI_THREAD_KEY(srv_error_monitor_thread, "ib_srv_err",
897 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
898 PSI_THREAD_KEY(srv_lock_timeout_thread, "ib_srv_lock_to",
899 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
900 PSI_THREAD_KEY(srv_master_thread, "ib_src_main", PSI_FLAG_SINGLETON, 0,
901 PSI_DOCUMENT_ME),
902 PSI_THREAD_KEY(srv_monitor_thread, "ib_srv_mon", PSI_FLAG_SINGLETON, 0,
903 PSI_DOCUMENT_ME),
904 PSI_THREAD_KEY(srv_purge_thread, "ib_srv_purge", PSI_FLAG_SINGLETON, 0,
905 PSI_DOCUMENT_ME),
906 PSI_THREAD_KEY(srv_worker_thread, "ib_srv_wkr", 0, 0, PSI_DOCUMENT_ME),
907 PSI_THREAD_KEY(trx_recovery_rollback_thread, "ib_tx_recov", 0, 0,
908 PSI_DOCUMENT_ME),
909 PSI_THREAD_KEY(page_flush_thread, "ib_pg_flush", 0, 0, PSI_DOCUMENT_ME),
910 PSI_THREAD_KEY(page_flush_coordinator_thread, "ib_pg_flush_co",
911 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
912 PSI_THREAD_KEY(fts_optimize_thread, "ib_fts_opt", PSI_FLAG_SINGLETON, 0,
913 PSI_DOCUMENT_ME),
914 PSI_THREAD_KEY(fts_parallel_merge_thread, "ib_fts_merge", 0, 0,
915 PSI_DOCUMENT_ME),
916 PSI_THREAD_KEY(fts_parallel_tokenization_thread, "ib_fts_token", 0, 0,
917 PSI_DOCUMENT_ME),
918 PSI_THREAD_KEY(srv_ts_alter_encrypt_thread, "ib_ts_encrypt",
919 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME),
920 PSI_THREAD_KEY(parallel_read_thread, "ib_par_rd", 0, 0, PSI_DOCUMENT_ME),
921 PSI_THREAD_KEY(parallel_rseg_init_thread, "ib_par_rseg", 0, 0,
922 PSI_DOCUMENT_ME),
923 PSI_THREAD_KEY(meb::redo_log_archive_consumer_thread, "ib_meb_rl",
924 PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME)};
925 #endif /* UNIV_PFS_THREAD */
926
927 #ifdef UNIV_PFS_IO
928 /* all_innodb_files array contains the type of files that are
929 performance schema instrumented if "UNIV_PFS_IO" is defined */
930 static PSI_file_info all_innodb_files[] = {
931 PSI_KEY(innodb_dblwr_file, 0, 0, PSI_DOCUMENT_ME),
932 PSI_KEY(innodb_tablespace_open_file, 0, 0, PSI_DOCUMENT_ME),
933 PSI_KEY(innodb_data_file, 0, 0, PSI_DOCUMENT_ME),
934 PSI_KEY(innodb_log_file, 0, 0, PSI_DOCUMENT_ME),
935 PSI_KEY(innodb_bmp_file, 0, 0, PSI_DOCUMENT_ME),
936 PSI_KEY(innodb_temp_file, 0, 0, PSI_DOCUMENT_ME),
937 PSI_KEY(innodb_arch_file, 0, 0, PSI_DOCUMENT_ME),
938 PSI_KEY(innodb_clone_file, 0, 0, PSI_DOCUMENT_ME),
939 PSI_KEY(meb::redo_log_archive_file, 0, 0, PSI_DOCUMENT_ME)};
940 #endif /* UNIV_PFS_IO */
941 #endif /* HAVE_PSI_INTERFACE */
942
943 13 static int default_encryption_key_id_validate(
944 /*=================================*/
945 THD *thd, /*!< in: thread handle */
946 SYS_VAR *var, /*!< in: pointer to system
947 variable */
948 void *save, /*!< out: immediate result
949 for update function */
950 st_mysql_value *value) /*!< in: incoming string */ {
951 long long intbuf;
952
953
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 DBUG_ENTER("default_encryption_key_id_validate");
954
955
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (value->val_int(value, &intbuf)) {
956 /* The value is NULL. That is invalid. */
957 DBUG_RETURN(1);
958 }
959
960 13 bool is_val_fixed = false;
961 13 auto key_id = intbuf;
962
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (intbuf < 0) {
963 3 key_id = 0;
964 3 is_val_fixed = true;
965
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 } else if (intbuf >= UINT_MAX32) {
966 3 key_id = UINT_MAX32 - 1;
967 3 is_val_fixed = true;
968 }
969
970
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (throw_bounds_warning(thd, "innodb_encryption_key_id", is_val_fixed,
971 intbuf)) {
972 DBUG_RETURN(1);
973 }
974
975
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist(
976 static_cast<uint>(key_id), server_uuid)) {
977 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
978 "InnoDB: cannot enable encryption, "
979 "keyring plugin is not available");
980 DBUG_RETURN(1);
981 }
982
983 13 *reinterpret_cast<ulong *>(save) = static_cast<ulong>(key_id);
984
985
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 DBUG_RETURN(0);
986 }
987
988 13 static void default_encryption_key_id_update(
989 THD *thd, // in: thread handle <]
990 SYS_VAR *var, // in: pointer to
991 // system variable */
992 void *var_ptr, // where the
993 // formal string goes */
994 const void *save) { // in: immediate result
995 // from check function
996 13 *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save);
997 13 }
998
999 static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG,
1000 "Default encryption key id used for table encryption.",
1001 default_encryption_key_id_validate,
1002 default_encryption_key_id_update,
1003 FIL_DEFAULT_ENCRYPTION_KEY, 0, UINT_MAX32 - 1, 0);
1004
1005 244 uint get_global_default_encryption_key_id_value() {
1006 244 return THDVAR(NULL, default_encryption_key_id);
1007 }
1008
1009 static MYSQL_THDVAR_UINT(records_in_range, PLUGIN_VAR_RQCMDARG,
1010 "Used to override the result of records_in_range(). "
1011 "Set to a positive number to override",
1012 NULL, NULL, 0,
1013 /* min */ 0, /* max */ INT_MAX, 0);
1014
1015 static MYSQL_THDVAR_UINT(force_index_records_in_range, PLUGIN_VAR_RQCMDARG,
1016 "Used to override the result of records_in_range() "
1017 "when FORCE INDEX is used.",
1018 NULL, NULL, 0,
1019 /* min */ 0, /* max */ INT_MAX, 0);
1020
1021 39 uint innodb_force_index_records_in_range(THD *thd) {
1022 39 return THDVAR(thd, force_index_records_in_range);
1023 }
1024
1025 7917 uint innodb_records_in_range(THD *thd) { return THDVAR(thd, records_in_range); }
1026
1027 /** Plugin update function to handle validation and then switch the
1028 innodb_doublewrite mode
1029 @param[in] thd thread handle
1030 @param[in] var pointer to system variable
1031 @param[in] var_ptr where the formal string goes
1032 @param[in] save immediate result from check function */
1033 92 static void doublewrite_update(THD *thd [[maybe_unused]],
1034 SYS_VAR *var [[maybe_unused]], void *var_ptr,
1035 const void *save) {
1036 92 ulong new_value = *static_cast<const ulong *>(save);
1037
1038
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 75 times.
92 if (dblwr::Mode::is_enabled_to_disabled(new_value)) {
1039 char msg[FN_REFLEN];
1040
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 snprintf(msg, sizeof(msg),
1041 "InnoDB: cannot change doublewrite mode to %s if"
1042 " doublewrite is enabled. Please shutdown and"
1043 " change value to %s",
1044 dblwr::Mode::to_string(new_value),
1045 dblwr::Mode::to_string(new_value));
1046
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 my_error(ER_WRONG_ARGUMENTS, MYF(0), msg);
1047 17 return;
1048 }
1049
1050
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 59 times.
75 if (dblwr::Mode::is_disabled_to_enabled(new_value)) {
1051 char msg[FN_REFLEN];
1052
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 snprintf(msg, sizeof(msg),
1053 "InnoDB: cannot change doublewrite mode to %s if"
1054 " doublewrite is disabled. Please shutdown and"
1055 " change value to %s",
1056 dblwr::Mode::to_string(new_value),
1057 dblwr::Mode::to_string(new_value));
1058
1059
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_error(ER_WRONG_ARGUMENTS, MYF(0), msg);
1060
1061 16 return;
1062 }
1063
1064
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 35 times.
59 if (dblwr::Mode::is_same(new_value)) {
1065 24 return;
1066 }
1067
1068 /* Handle DETECT_AND_RECOVER to DETECT_ONLY
1069 1. Check if DETECT_ONLY setup is already initalized. If not, intialize
1070 DETECT_ONLY files and structures.
1071 2. Flush the partially filled dblwr buffers. */
1072
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 18 times.
35 if (dblwr::Mode::is_reduced_low(new_value)) {
1073 17 dberr_t err = dblwr::enable_reduced();
1074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (err != DB_SUCCESS) {
1075 char msg[FN_REFLEN];
1076 snprintf(msg, sizeof(msg),
1077 "InnoDB: cannot change doublewrite mode to %s."
1078 " Please check if doublewrite directory is writable"
1079 " Error code: %d",
1080 dblwr::Mode::to_string(new_value), err);
1081 my_error(ER_WRONG_ARGUMENTS, MYF(0), msg);
1082 return;
1083 }
1084 }
1085
1086 /* Handle DETECT_ONLY to DETECT_AND_RECOVER.
1087 1. Flush partially filled reduced dblwr buffers */
1088 35 dblwr::force_flush_all();
1089
1090 35 *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save);
1091 }
1092
1093 /** Set up InnoDB API callback function array */
1094 /*
1095 Generates array elements which look like:
1096 (ib_cb_t)ib_cursor_open_table,
1097 for each api function.
1098 */
1099 #define INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM(stem) (ib_cb_t) ib_##stem,
1100
1101 static ib_cb_t innodb_api_cb[] = {
1102 FOR_EACH_API_METHOD_NAME_STEM(INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM)};
1103
1104 static int innodb_check_session_admin(THD *thd, SYS_VAR *self, void *save,
1105 struct st_mysql_value *value);
1106
1107 /**Check whether valid argument given to innobase_*_stopword_table.
1108 This function is registered as a callback with MySQL.
1109 @param[in] thd thread handle
1110 @param[in] var pointer to system variable
1111 @param[out] save immediate result for update function
1112 @param[in] value incoming string
1113 @return 0 for valid stopword table */
1114 static int innodb_stopword_table_validate(THD *thd, SYS_VAR *var, void *save,
1115 struct st_mysql_value *value);
1116
1117 /** Validate passed-in "value" is a valid directory name.
1118 This function is registered as a callback with MySQL.
1119 @param[in,out] thd thread handle
1120 @param[out] save immediate result for update
1121 @param[in] value incoming string
1122 @return 0 for valid name */
1123 17 static int innodb_tmpdir_validate(THD *thd, SYS_VAR *, void *save,
1124 struct st_mysql_value *value) {
1125 char *alter_tmp_dir;
1126 char *innodb_tmp_dir;
1127 char buff[OS_FILE_MAX_PATH];
1128 17 int len = sizeof(buff);
1129 char tmp_abs_path[FN_REFLEN + 2];
1130
1131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 ut_ad(save != nullptr);
1132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 ut_ad(value != nullptr);
1133
1134
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if (check_global_access(thd, FILE_ACL)) {
1135 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1136 "InnoDB: FILE Permissions required");
1137 *static_cast<const char **>(save) = nullptr;
1138 return (1);
1139 }
1140
1141
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 alter_tmp_dir = (char *)value->val_str(value, buff, &len);
1142
1143
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8 times.
17 if (!alter_tmp_dir) {
1144 9 *static_cast<const char **>(save) = alter_tmp_dir;
1145 9 return (0);
1146 }
1147
1148
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (strlen(alter_tmp_dir) > FN_REFLEN) {
1149
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1150 "Path length should not exceed %d bytes", FN_REFLEN);
1151 1 *static_cast<const char **>(save) = nullptr;
1152 1 return (1);
1153 }
1154
1155 7 Fil_path::normalize(alter_tmp_dir);
1156
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_realpath(tmp_abs_path, alter_tmp_dir, 0);
1157 7 size_t tmp_abs_len = strlen(tmp_abs_path);
1158
1159
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (my_access(tmp_abs_path, F_OK)) {
1160
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1161 "InnoDB: Path doesn't exist.");
1162 2 *static_cast<const char **>(save) = nullptr;
1163 2 return (1);
1164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (my_access(tmp_abs_path, R_OK | W_OK)) {
1165 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1166 "InnoDB: Server doesn't have permission in "
1167 "the given location.");
1168 *static_cast<const char **>(save) = nullptr;
1169 return (1);
1170 }
1171
1172 MY_STAT stat_info_dir;
1173
1174
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) {
1175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) {
1176 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1177 "Given path is not a directory. ");
1178 *static_cast<const char **>(save) = nullptr;
1179 return (1);
1180 }
1181 }
1182
1183
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
5 if (!is_mysql_datadir_path(tmp_abs_path)) {
1184
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
1185 "InnoDB: Path location should not be same as "
1186 "mysql data directory location.");
1187 1 *static_cast<const char **>(save) = nullptr;
1188 1 return (1);
1189 }
1190
1191 innodb_tmp_dir =
1192
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 static_cast<char *>(thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1));
1193 4 *static_cast<const char **>(save) = innodb_tmp_dir;
1194 4 return (0);
1195 }
1196
1197 /** Empty free list algorithm.
1198 Checks if buffer pool is big enough to enable backoff algorithm.
1199 InnoDB empty free list algorithm backoff requires free pages
1200 from LRU for the best performance.
1201 buf_LRU_buf_pool_running_out cancels query if 1/4 of
1202 buffer pool belongs to LRU or freelist.
1203 At the same time buf_flush_LRU_list_batch
1204 keeps up to BUF_LRU_MIN_LEN in LRU.
1205 In order to avoid deadlock backoff requires buffer pool
1206 to be at least 4*BUF_LRU_MIN_LEN,
1207 but flush peformance is bad because of trashing
1208 and additional BUF_LRU_MIN_LEN pages are requested.
1209 @param[in] algorithm desired algorithm from srv_empty_free_list_t
1210 @param[in] new_buf_pool_sz requested buffer pool size
1211 @return true if it's possible to enable backoff. */
1212 12067 static bool innodb_empty_free_list_algorithm_allowed(
1213 srv_empty_free_list_t algorithm, long long new_buf_pool_sz = 0) {
1214
2/2
✓ Branch 0 taken 12038 times.
✓ Branch 1 taken 29 times.
12067 if (!new_buf_pool_sz) new_buf_pool_sz = srv_buf_pool_size;
1215
1216 12067 const long long buf_pool_pages =
1217 12067 new_buf_pool_sz / srv_page_size / srv_buf_pool_instances;
1218
1219
4/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 12014 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 5 times.
12067 return (buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) ||
1220 12067 algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
1221 }
1222
1223 /** Gets field offset for a field in a table.
1224 @param[in] table MySQL table object
1225 @param[in] field MySQL field object
1226 @return offset */
1227 static inline uint get_field_offset(const TABLE *table, const Field *field);
1228
1229 static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
1230 "Enable InnoDB locking in LOCK TABLES",
1231 /* check_func */ nullptr, /* update_func */ nullptr,
1232 /* default */ true);
1233
1234 static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
1235 "Use strict mode when evaluating create options.",
1236 innodb_check_session_admin, nullptr, true);
1237
1238 static MYSQL_THDVAR_BOOL(ft_enable_stopword,
1239 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_HINTUPDATEABLE,
1240 "Create FTS index with stopword.", nullptr, nullptr,
1241 /* default */ true);
1242
1243 static MYSQL_THDVAR_ULONG(lock_wait_timeout,
1244 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE,
1245 "Timeout in seconds an InnoDB transaction may wait "
1246 "for a lock before being rolled back. Values above "
1247 "100000000 disable the timeout.",
1248 nullptr, nullptr, 50, 1, 1024 * 1024 * 1024, 0);
1249
1250 static MYSQL_THDVAR_STR(
1251 ft_user_stopword_table,
1252 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_HINTUPDATEABLE,
1253 "User supplied stopword table name, effective in the session level.",
1254 innodb_stopword_table_validate, nullptr, nullptr);
1255
1256 static MYSQL_THDVAR_STR(tmpdir,
1257 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC |
1258 PLUGIN_VAR_HINTUPDATEABLE,
1259 "Directory for temporary non-tablespace files.",
1260 innodb_tmpdir_validate, nullptr, nullptr);
1261
1262 static MYSQL_THDVAR_BOOL(ft_ignore_stopwords, PLUGIN_VAR_OPCMDARG,
1263 "Instruct FTS to ignore stopwords.", nullptr, nullptr,
1264 false);
1265
1266 static MYSQL_THDVAR_ULONG(parallel_read_threads, PLUGIN_VAR_RQCMDARG,
1267 "Number of threads to do parallel read.", nullptr,
1268 nullptr, 4, /* Default. */
1269 1, /* Minimum. */
1270 Parallel_reader::MAX_THREADS, /* Maxumum. */
1271 0);
1272
1273 static MYSQL_THDVAR_ULONG(ddl_buffer_size, PLUGIN_VAR_RQCMDARG,
1274 "Maximum size of memory to use (in bytes) for DDL.",
1275 nullptr, nullptr, 1048576, /* Default. */
1276 65536, /* Minimum. */
1277 4294967295, 0); /* Maximum. */
1278
1279 static MYSQL_THDVAR_ULONG(ddl_threads, PLUGIN_VAR_RQCMDARG,
1280 "Maximum number of threads to use for DDL.", nullptr,
1281 nullptr, 4, /* Default. */
1282 1, /* Minimum. */
1283 64, 0); /* Maximum. */
1284
1285 static SHOW_VAR innodb_status_variables[] = {
1286 {"background_log_sync", (char *)&export_vars.innodb_background_log_sync,
1287 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1288 {"buffer_pool_dump_status",
1289 (char *)&export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR,
1290 SHOW_SCOPE_GLOBAL},
1291 {"buffer_pool_load_status",
1292 (char *)&export_vars.innodb_buffer_pool_load_status, SHOW_CHAR,
1293 SHOW_SCOPE_GLOBAL},
1294 {"buffer_pool_resize_status",
1295 (char *)&export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR,
1296 SHOW_SCOPE_GLOBAL},
1297 {"buffer_pool_pages_data",
1298 (char *)&export_vars.innodb_buffer_pool_pages_data, SHOW_LONG,
1299 SHOW_SCOPE_GLOBAL},
1300 {"buffer_pool_bytes_data",
1301 (char *)&export_vars.innodb_buffer_pool_bytes_data, SHOW_LONG,
1302 SHOW_SCOPE_GLOBAL},
1303 {"buffer_pool_pages_dirty",
1304 (char *)&export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG,
1305 SHOW_SCOPE_GLOBAL},
1306 {"buffer_pool_bytes_dirty",
1307 (char *)&export_vars.innodb_buffer_pool_bytes_dirty, SHOW_LONG,
1308 SHOW_SCOPE_GLOBAL},
1309 {"buffer_pool_pages_flushed",
1310 (char *)&export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG,
1311 SHOW_SCOPE_GLOBAL},
1312 {"buffer_pool_pages_free",
1313 (char *)&export_vars.innodb_buffer_pool_pages_free, SHOW_LONG,
1314 SHOW_SCOPE_GLOBAL},
1315 #ifdef UNIV_DEBUG
1316 {"buffer_pool_pages_latched",
1317 (char *)&export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG,
1318 SHOW_SCOPE_GLOBAL},
1319 #endif /* UNIV_DEBUG */
1320 {"buffer_pool_pages_LRU_flushed",
1321 (char *)&export_vars.innodb_buffer_pool_pages_LRU_flushed, SHOW_LONG,
1322 SHOW_SCOPE_GLOBAL},
1323 {"buffer_pool_pages_made_not_young",
1324 (char *)&export_vars.innodb_buffer_pool_pages_made_not_young, SHOW_LONG,
1325 SHOW_SCOPE_GLOBAL},
1326 {"buffer_pool_pages_made_young",
1327 (char *)&export_vars.innodb_buffer_pool_pages_made_young, SHOW_LONG,
1328 SHOW_SCOPE_GLOBAL},
1329 {"buffer_pool_pages_misc",
1330 (char *)&export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG,
1331 SHOW_SCOPE_GLOBAL},
1332 {"buffer_pool_pages_old", (char *)&export_vars.innodb_buffer_pool_pages_old,
1333 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1334 {"buffer_pool_pages_total",
1335 (char *)&export_vars.innodb_buffer_pool_pages_total, SHOW_LONG,
1336 SHOW_SCOPE_GLOBAL},
1337 {"buffer_pool_read_ahead_rnd",
1338 (char *)&export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG,
1339 SHOW_SCOPE_GLOBAL},
1340 {"buffer_pool_read_ahead",
1341 (char *)&export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG,
1342 SHOW_SCOPE_GLOBAL},
1343 {"buffer_pool_read_ahead_evicted",
1344 (char *)&export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG,
1345 SHOW_SCOPE_GLOBAL},
1346 {"buffer_pool_read_requests",
1347 (char *)&export_vars.innodb_buffer_pool_read_requests, SHOW_LONG,
1348 SHOW_SCOPE_GLOBAL},
1349 {"buffer_pool_reads", (char *)&export_vars.innodb_buffer_pool_reads,
1350 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1351 {"buffer_pool_wait_free", (char *)&export_vars.innodb_buffer_pool_wait_free,
1352 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1353 {"buffer_pool_write_requests",
1354 (char *)&export_vars.innodb_buffer_pool_write_requests, SHOW_LONG,
1355 SHOW_SCOPE_GLOBAL},
1356 {"checkpoint_age", (char *)&export_vars.innodb_checkpoint_age, SHOW_LONG,
1357 SHOW_SCOPE_GLOBAL},
1358 {"checkpoint_max_age", (char *)&export_vars.innodb_checkpoint_max_age,
1359 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1360 {"data_fsyncs", (char *)&export_vars.innodb_data_fsyncs, SHOW_LONG,
1361 SHOW_SCOPE_GLOBAL},
1362 {"data_pending_fsyncs", (char *)&export_vars.innodb_data_pending_fsyncs,
1363 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1364 {"data_pending_reads", (char *)&export_vars.innodb_data_pending_reads,
1365 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1366 {"data_pending_writes", (char *)&export_vars.innodb_data_pending_writes,
1367 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1368 {"data_read", (char *)&export_vars.innodb_data_read, SHOW_LONG,
1369 SHOW_SCOPE_GLOBAL},
1370 {"data_reads", (char *)&export_vars.innodb_data_reads, SHOW_LONG,
1371 SHOW_SCOPE_GLOBAL},
1372 {"data_writes", (char *)&export_vars.innodb_data_writes, SHOW_LONG,
1373 SHOW_SCOPE_GLOBAL},
1374 {"data_written", (char *)&export_vars.innodb_data_written, SHOW_LONG,
1375 SHOW_SCOPE_GLOBAL},
1376 {"dblwr_pages_written", (char *)&export_vars.innodb_dblwr_pages_written,
1377 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1378 {"dblwr_writes", (char *)&export_vars.innodb_dblwr_writes, SHOW_LONG,
1379 SHOW_SCOPE_GLOBAL},
1380 {"ibuf_free_list", (char *)&export_vars.innodb_ibuf_free_list, SHOW_LONG,
1381 SHOW_SCOPE_GLOBAL},
1382 {"ibuf_segment_size", (char *)&export_vars.innodb_ibuf_segment_size,
1383 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1384 {"redo_log_read_only", (char *)&export_vars.innodb_redo_log_read_only,
1385 SHOW_BOOL, SHOW_SCOPE_GLOBAL},
1386 {"redo_log_uuid", (char *)&export_vars.innodb_redo_log_uuid, SHOW_LONGLONG,
1387 SHOW_SCOPE_GLOBAL},
1388 {"redo_log_checkpoint_lsn",
1389 (char *)&export_vars.innodb_redo_log_checkpoint_lsn, SHOW_LONGLONG,
1390 SHOW_SCOPE_GLOBAL},
1391 {"redo_log_current_lsn", (char *)&export_vars.innodb_redo_log_current_lsn,
1392 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1393 {"redo_log_flushed_to_disk_lsn",
1394 (char *)&export_vars.innodb_redo_log_flushed_to_disk_lsn, SHOW_LONGLONG,
1395 SHOW_SCOPE_GLOBAL},
1396 {"redo_log_logical_size", (char *)&export_vars.innodb_redo_log_logical_size,
1397 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1398 {"redo_log_physical_size",
1399 (char *)&export_vars.innodb_redo_log_physical_size, SHOW_LONGLONG,
1400 SHOW_SCOPE_GLOBAL},
1401 {"redo_log_capacity_resized",
1402 (char *)&export_vars.innodb_redo_log_capacity_resized, SHOW_LONGLONG,
1403 SHOW_SCOPE_GLOBAL},
1404 {"redo_log_resize_status",
1405 (char *)&export_vars.innodb_redo_log_resize_status, SHOW_CHAR,
1406 SHOW_SCOPE_GLOBAL},
1407 {"log_waits", (char *)&export_vars.innodb_log_waits, SHOW_LONG,
1408 SHOW_SCOPE_GLOBAL},
1409 {"log_write_requests", (char *)&export_vars.innodb_log_write_requests,
1410 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1411 {"log_writes", (char *)&export_vars.innodb_log_writes, SHOW_LONG,
1412 SHOW_SCOPE_GLOBAL},
1413 {"lsn_current", (char *)&export_vars.innodb_lsn_current, SHOW_LONGLONG,
1414 SHOW_SCOPE_GLOBAL},
1415 {"lsn_flushed", (char *)&export_vars.innodb_lsn_flushed, SHOW_LONGLONG,
1416 SHOW_SCOPE_GLOBAL},
1417 {"lsn_last_checkpoint", (char *)&export_vars.innodb_lsn_last_checkpoint,
1418 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1419 {"master_thread_active_loops",
1420 (char *)&export_vars.innodb_master_thread_active_loops, SHOW_LONG,
1421 SHOW_SCOPE_GLOBAL},
1422 {"master_thread_idle_loops",
1423 (char *)&export_vars.innodb_master_thread_idle_loops, SHOW_LONG,
1424 SHOW_SCOPE_GLOBAL},
1425 {"max_trx_id", (char *)&export_vars.innodb_max_trx_id, SHOW_LONGLONG,
1426 SHOW_SCOPE_GLOBAL},
1427 {"oldest_view_low_limit_trx_id",
1428 (char *)&export_vars.innodb_oldest_view_low_limit_trx_id, SHOW_LONGLONG,
1429 SHOW_SCOPE_GLOBAL},
1430 {"os_log_fsyncs", (char *)&export_vars.innodb_os_log_fsyncs, SHOW_LONG,
1431 SHOW_SCOPE_GLOBAL},
1432 {"os_log_pending_fsyncs", (char *)&export_vars.innodb_os_log_pending_fsyncs,
1433 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1434 {"os_log_pending_writes", (char *)&export_vars.innodb_os_log_pending_writes,
1435 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1436 {"os_log_written", (char *)&export_vars.innodb_os_log_written,
1437 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1438 {"page_size", (char *)&export_vars.innodb_page_size, SHOW_LONG,
1439 SHOW_SCOPE_GLOBAL},
1440 {"pages_created", (char *)&export_vars.innodb_pages_created, SHOW_LONG,
1441 SHOW_SCOPE_GLOBAL},
1442 {"pages_read", (char *)&export_vars.innodb_pages_read, SHOW_LONG,
1443 SHOW_SCOPE_GLOBAL},
1444 {"pages0_read", (char *)&export_vars.innodb_page0_read, SHOW_LONG,
1445 SHOW_SCOPE_GLOBAL},
1446 {"pages_written", (char *)&export_vars.innodb_pages_written, SHOW_LONG,
1447 SHOW_SCOPE_GLOBAL},
1448 {"purge_trx_id", (char *)&export_vars.innodb_purge_trx_id, SHOW_LONGLONG,
1449 SHOW_SCOPE_GLOBAL},
1450 {"purge_undo_no", (char *)&export_vars.innodb_purge_undo_no, SHOW_LONGLONG,
1451 SHOW_SCOPE_GLOBAL},
1452 {"redo_log_enabled", (char *)&export_vars.innodb_redo_log_enabled,
1453 SHOW_BOOL, SHOW_SCOPE_GLOBAL},
1454 {"row_lock_current_waits",
1455 (char *)&export_vars.innodb_row_lock_current_waits, SHOW_LONG,
1456 SHOW_SCOPE_GLOBAL},
1457 {"row_lock_time", (char *)&export_vars.innodb_row_lock_time, SHOW_LONGLONG,
1458 SHOW_SCOPE_GLOBAL},
1459 {"row_lock_time_avg", (char *)&export_vars.innodb_row_lock_time_avg,
1460 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1461 {"row_lock_time_max", (char *)&export_vars.innodb_row_lock_time_max,
1462 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1463 {"row_lock_waits", (char *)&export_vars.innodb_row_lock_waits, SHOW_LONG,
1464 SHOW_SCOPE_GLOBAL},
1465 {"rows_deleted", (char *)&export_vars.innodb_rows_deleted, SHOW_LONG,
1466 SHOW_SCOPE_GLOBAL},
1467 {"rows_inserted", (char *)&export_vars.innodb_rows_inserted, SHOW_LONG,
1468 SHOW_SCOPE_GLOBAL},
1469 {"rows_read", (char *)&export_vars.innodb_rows_read, SHOW_LONG,
1470 SHOW_SCOPE_GLOBAL},
1471 {"rows_updated", (char *)&export_vars.innodb_rows_updated, SHOW_LONG,
1472 SHOW_SCOPE_GLOBAL},
1473 {"system_rows_deleted", (char *)&export_vars.innodb_system_rows_deleted,
1474 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1475 {"system_rows_inserted", (char *)&export_vars.innodb_system_rows_inserted,
1476 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1477 {"system_rows_read", (char *)&export_vars.innodb_system_rows_read,
1478 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1479 {"system_rows_updated", (char *)&export_vars.innodb_system_rows_updated,
1480 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1481 {"sampled_pages_read", (char *)&export_vars.innodb_sampled_pages_read,
1482 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1483 {"sampled_pages_skipped", (char *)&export_vars.innodb_sampled_pages_skipped,
1484 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1485 {"num_open_files", (char *)&export_vars.innodb_num_open_files, SHOW_LONG,
1486 SHOW_SCOPE_GLOBAL},
1487 {"truncated_status_writes",
1488 (char *)&export_vars.innodb_truncated_status_writes, SHOW_LONG,
1489 SHOW_SCOPE_GLOBAL},
1490 {"undo_tablespaces_total",
1491 (char *)&export_vars.innodb_undo_tablespaces_total, SHOW_LONG,
1492 SHOW_SCOPE_GLOBAL},
1493 {"undo_tablespaces_implicit",
1494 (char *)&export_vars.innodb_undo_tablespaces_implicit, SHOW_LONG,
1495 SHOW_SCOPE_GLOBAL},
1496 {"undo_tablespaces_explicit",
1497 (char *)&export_vars.innodb_undo_tablespaces_explicit, SHOW_LONG,
1498 SHOW_SCOPE_GLOBAL},
1499 {"undo_tablespaces_active",
1500 (char *)&export_vars.innodb_undo_tablespaces_active, SHOW_LONG,
1501 SHOW_SCOPE_GLOBAL},
1502 #ifdef UNIV_DEBUG
1503 {"purge_trx_id_age", (char *)&export_vars.innodb_purge_trx_id_age,
1504 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1505 {"purge_view_trx_id_age", (char *)&export_vars.innodb_purge_view_trx_id_age,
1506 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1507 {"ahi_drop_lookups", (char *)&export_vars.innodb_ahi_drop_lookups,
1508 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1509 #endif /* UNIV_DEBUG */
1510 {"secondary_index_triggered_cluster_reads",
1511 (char *)&export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG,
1512 SHOW_SCOPE_GLOBAL},
1513 {"secondary_index_triggered_cluster_reads_avoided",
1514 (char *)&export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG,
1515 SHOW_SCOPE_GLOBAL},
1516 {"buffered_aio_submitted",
1517 (char *)&export_vars.innodb_buffered_aio_submitted, SHOW_LONG,
1518 SHOW_SCOPE_GLOBAL},
1519
1520 {"scan_pages_contiguous",
1521 (char *)&export_vars.innodb_fragmentation_stats.scan_pages_contiguous,
1522 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1523 {"scan_pages_disjointed",
1524 (char *)&export_vars.innodb_fragmentation_stats.scan_pages_disjointed,
1525 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1526 {"scan_pages_total_seek_distance",
1527 (char *)&export_vars.innodb_fragmentation_stats
1528 .scan_pages_total_seek_distance,
1529 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1530 {"scan_data_size",
1531 (char *)&export_vars.innodb_fragmentation_stats.scan_data_size, SHOW_LONG,
1532 SHOW_SCOPE_GLOBAL},
1533 {"scan_deleted_recs_size",
1534 (char *)&export_vars.innodb_fragmentation_stats.scan_deleted_recs_size,
1535 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1536 {"encryption_n_merge_blocks_encrypted",
1537 (char *)&export_vars.innodb_n_merge_blocks_encrypted, SHOW_LONGLONG,
1538 SHOW_SCOPE_GLOBAL},
1539 {"encryption_n_merge_blocks_decrypted",
1540 (char *)&export_vars.innodb_n_merge_blocks_decrypted, SHOW_LONGLONG,
1541 SHOW_SCOPE_GLOBAL},
1542 {"encryption_n_rowlog_blocks_encrypted",
1543 (char *)&export_vars.innodb_n_rowlog_blocks_encrypted, SHOW_LONGLONG,
1544 SHOW_SCOPE_GLOBAL},
1545 {"encryption_n_rowlog_blocks_decrypted",
1546 (char *)&export_vars.innodb_n_rowlog_blocks_decrypted, SHOW_LONGLONG,
1547 SHOW_SCOPE_GLOBAL},
1548 {"encryption_redo_key_version",
1549 (char *)&export_vars.innodb_redo_key_version, SHOW_LONGLONG,
1550 SHOW_SCOPE_GLOBAL},
1551 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL},
1552 /* Encryption */
1553 {"encryption_rotation_pages_read_from_cache",
1554 (char *)&export_vars.innodb_encryption_rotation_pages_read_from_cache,
1555 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1556 {"encryption_rotation_pages_read_from_disk",
1557 (char *)&export_vars.innodb_encryption_rotation_pages_read_from_disk,
1558 SHOW_LONG, SHOW_SCOPE_GLOBAL},
1559 {"encryption_rotation_pages_modified",
1560 (char *)&export_vars.innodb_encryption_rotation_pages_modified, SHOW_LONG,
1561 SHOW_SCOPE_GLOBAL},
1562 {"encryption_rotation_pages_flushed",
1563 (char *)&export_vars.innodb_encryption_rotation_pages_flushed, SHOW_LONG,
1564 SHOW_SCOPE_GLOBAL},
1565 {"encryption_rotation_estimated_iops",
1566 (char *)&export_vars.innodb_encryption_rotation_estimated_iops, SHOW_LONG,
1567 SHOW_SCOPE_GLOBAL},
1568 {"encryption_key_rotation_list_length",
1569 (char *)&export_vars.innodb_key_rotation_list_length, SHOW_LONGLONG,
1570 SHOW_SCOPE_GLOBAL},
1571 {"num_pages_encrypted", (char *)&export_vars.innodb_pages_encrypted,
1572 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1573 {"num_pages_decrypted", (char *)&export_vars.innodb_pages_decrypted,
1574 SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
1575 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}};
1576
1577 /** Handling the shared INNOBASE_SHARE structure that is needed to provide table
1578 locking. Register the table name if it doesn't exist in the hash table. */
1579 static INNOBASE_SHARE *get_share(
1580 const char *table_name); /*!< in: table to lookup */
1581
1582 /** Free the shared object that was registered with get_share(). */
1583 static void free_share(INNOBASE_SHARE *share); /*!< in/own: share to free */
1584
1585 /** Calls free_share and assign nullptr to share.
1586 @param[in,out] share table share to free */
1587 4434068 static void free_share_and_nullify(
1588 INNOBASE_SHARE **share) /*!< in/own: table share to free */
1589 {
1590 4434068 free_share(*share);
1591 4434068 *share = nullptr;
1592 4434068 }
1593
1594 /** Frees a possible InnoDB trx object associated with the current THD.
1595 @return 0 or error number */
1596 static int innobase_close_connection(
1597 handlerton *hton, /*!< in/out: InnoDB handlerton */
1598 THD *thd); /*!< in: MySQL thread handle for
1599 which to close the connection */
1600
1601 /** Cancel any pending lock request associated with the current THD. */
1602 static void innobase_kill_connection(
1603 handlerton *hton, /*!< in/out: InnoDB handlerton */
1604 THD *thd); /*!< in: MySQL thread handle for
1605 which to close the connection */
1606
1607 /** Commits a transaction in an InnoDB database or marks an SQL statement
1608 ended.
1609 @return 0 */
1610 static int innobase_commit(handlerton *hton, /*!< in/out: InnoDB handlerton */
1611 THD *thd, /*!< in: MySQL thread handle of the
1612 user for whom the transaction should
1613 be committed */
1614 bool commit_trx); /*!< in: true - commit transaction
1615 false - the current SQL statement
1616 ended */
1617
1618 /** Rolls back a transaction to a savepoint.
1619 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
1620 given name */
1621 static int innobase_rollback(handlerton *hton, /*!< in/out: InnoDB handlerton */
1622 THD *thd, /*!< in: handle to the MySQL thread
1623 of the user whose transaction should
1624 be rolled back */
1625 bool rollback_trx); /*!< in: true - rollback entire
1626 transaction false - rollback
1627 the current statement only */
1628
1629 /** Rolls back a transaction to a savepoint.
1630 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
1631 given name */
1632 static int innobase_rollback_to_savepoint(
1633 handlerton *hton, /*!< in/out: InnoDB handlerton */
1634 THD *thd, /*!< in: handle to the MySQL thread of
1635 the user whose XA transaction should
1636 be rolled back to savepoint */
1637 void *savepoint); /*!< in: savepoint data */
1638
1639 /** Check whether innodb state allows to safely release MDL locks after
1640 rollback to savepoint.
1641 @return true if it is safe, false if its not safe. */
1642 static bool innobase_rollback_to_savepoint_can_release_mdl(
1643 handlerton *hton, /*!< in/out: InnoDB handlerton */
1644 THD *thd); /*!< in: handle to the MySQL thread of
1645 the user whose XA transaction should
1646 be rolled back to savepoint */
1647
1648 /** Sets a transaction savepoint.
1649 @return always 0, that is, always succeeds */
1650 static int innobase_savepoint(
1651 handlerton *hton, /*!< in/out: InnoDB handlerton */
1652 THD *thd, /*!< in: handle to the MySQL thread of
1653 the user's XA transaction for which
1654 we need to take a savepoint */
1655 void *savepoint); /*!< in: savepoint data */
1656
1657 /** Release transaction savepoint name.
1658 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
1659 given name */
1660 static int innobase_release_savepoint(
1661 handlerton *hton, /*!< in/out: handlerton for InnoDB */
1662 THD *thd, /*!< in: handle to the MySQL thread
1663 of the user whose transaction's
1664 savepoint should be released */
1665 void *savepoint); /*!< in: savepoint data */
1666
1667 /** Function for constructing an InnoDB table handler instance.
1668 @param[in,out] hton handlerton for InnoDB
1669 @param[in] table MySQL table
1670 @param[in] partitioned Indicates whether table is partitioned
1671 @param[in] mem_root memory context */
1672 static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table,
1673 bool partitioned, MEM_ROOT *mem_root);
1674
1675 /** Retrieve table satistics.
1676 @param[in] db_name database name
1677 @param[in] table_name table name
1678 @param[in] se_private_id The internal id of the table
1679 @param[in] ts_se_private_data Tablespace SE Private data
1680 @param[in] tbl_se_private_data Table SE private data
1681 @param[in] stat_flags flags used to retrieve specific stats
1682 @param[in,out] stats structure to save the
1683 retrieved statistics
1684 @return false on success, true on failure */
1685 static bool innobase_get_table_statistics(
1686 const char *db_name, const char *table_name, dd::Object_id se_private_id,
1687 const dd::Properties &ts_se_private_data,
1688 const dd::Properties &tbl_se_private_data, uint stat_flags,
1689 ha_statistics *stats);
1690
1691 /** Retrieve index column cardinality.
1692 @param[in] db_name name of schema
1693 @param[in] table_name name of table
1694 @param[in] index_name name of index
1695 @param[in] index_ordinal_position position of index
1696 @param[in] column_ordinal_position position of column in index
1697 @param[in] se_private_id the internal id of the table
1698 @param[in,out] cardinality cardinality of index column
1699 @retval false success
1700 @retval true failure */
1701 static bool innobase_get_index_column_cardinality(
1702 const char *db_name, const char *table_name, const char *index_name,
1703 uint index_ordinal_position, uint column_ordinal_position,
1704 dd::Object_id se_private_id, ulonglong *cardinality);
1705
1706 /** Retrieve ha_tablespace_statistics for the tablespace.
1707
1708 @param tablespace_name Tablespace_name
1709 @param file_name Data file name.
1710 @param ts_se_private_data Tablespace SE private data.
1711 @param[out] stats Contains tablespace
1712 statistics read from SE.
1713 @return false on success, true on failure */
1714 static bool innobase_get_tablespace_statistics(
1715 const char *tablespace_name, const char *file_name,
1716 const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats);
1717
1718 static bool innobase_is_tablespace_keyring_pre_v3_encrypted(
1719 const dd::Tablespace &tablespace, int &error);
1720 /** Retrieve the tablespace type.
1721
1722 @param space Tablespace object.
1723 @param[out] space_type Tablespace category.
1724 @return false on success, true on failure */
1725 static bool innobase_get_tablespace_type(const dd::Tablespace &space,
1726 Tablespace_type *space_type);
1727
1728 /** Get the tablespace type given the name.
1729
1730 @param[in] tablespace_name tablespace name
1731 @param[out] space_type type of space
1732
1733 @return Operation status.
1734 @retval false on success and true for failure.
1735 */
1736 static bool innobase_get_tablespace_type_by_name(const char *tablespace_name,
1737 Tablespace_type *space_type);
1738
1739 /** Perform post-commit/rollback cleanup after DDL statement.
1740 @param[in,out] thd connection thread */
1741 static void innobase_post_ddl(THD *thd);
1742
1743 /** Check if types of child and parent columns in foreign key are compatible.
1744 @param[in] child_column_type Child column type description.
1745 @param[in] parent_column_type Parent column type description.
1746 @param[in] check_charsets Indicates whether we need to check
1747 that charsets of string columns
1748 match. Which is true in most cases.
1749 @return True if types are compatible, False if not. */
1750 static bool innodb_check_fk_column_compat(
1751 const Ha_fk_column_type *child_column_type,
1752 const Ha_fk_column_type *parent_column_type, bool check_charsets);
1753
1754 /** @brief Initialize the default value of innodb_commit_concurrency.
1755
1756 Once InnoDB is running, the innodb_commit_concurrency must not change
1757 from zero to nonzero. (Bug #42101)
1758
1759 The initial default value is 0, and without this extra initialization,
1760 SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
1761 to 0, even if it was initially set to nonzero at the command line
1762 or configuration file. */
1763 static void innobase_commit_concurrency_init_default();
1764
1765 /** This function is used to prepare an X/Open XA distributed transaction.
1766 @return 0 or error number */
1767 static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */
1768 THD *thd, /*!< in: handle to the MySQL thread of
1769 the user whose XA transaction should
1770 be prepared */
1771 bool all); /*!< in: true - prepare transaction
1772 false - the current SQL statement
1773 ended */
1774 /** This function is used to recover X/Open XA distributed transactions.
1775 @return number of prepared transactions stored in xid_list */
1776 static int innobase_xa_recover(
1777 handlerton *hton, /*!< in: InnoDB handlerton */
1778 XA_recover_txn *txn_list, /*!< in/out: prepared transactions */
1779 uint len, /*!< in: number of slots in xid_list */
1780 MEM_ROOT *mem_root); /*!< in: memory for table names */
1781 /** Find prepared transactions that are marked as prepared in TC, for recovery
1782 purposes.
1783 @param[in] hton InnoDB handlerton
1784 @param[in,out] xa_list prepared transactions state
1785 @return 0 if successful or error number */
1786 static int innobase_xa_recover_prepared_in_tc(handlerton *hton,
1787 Xa_state_list &xa_list);
1788 /** This function is used to commit one X/Open XA distributed transaction
1789 which is in the prepared state
1790 @return 0 or error number */
1791 static xa_status_code innobase_commit_by_xid(
1792 handlerton *hton, /*!< in: InnoDB handlerton */
1793 XID *xid); /*!< in: X/Open XA transaction
1794 identification */
1795 /** This function is used to rollback one X/Open XA distributed transaction
1796 which is in the prepared state
1797 @return 0 or error number */
1798 static xa_status_code innobase_rollback_by_xid(
1799 handlerton *hton, /*!< in: InnoDB handlerton */
1800 XID *xid); /*!< in: X/Open XA transaction
1801 identification */
1802 /** This function is used to write mark an X/Open XA distributed transaction
1803 as been prepared in the server transaction coordinator
1804 @param[in] hton InnoDB handlerton
1805 @param[in] thd handle to the MySQL thread of the user whose XA transaction
1806 should be prepared
1807 @return 0 or error number */
1808 static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd);
1809 /** Mark an X/Open XA distributed transaction
1810 as been prepared in the server transaction coordinator
1811 @param[in] hton InnoDB handlerton
1812 @param[in] xid X/Open XA transaction identification the MySQL thread of the
1813 user whosefo the XA transaction that should be prepared
1814 @return XA_OK or error number */
1815 static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton,
1816 XID *xid);
1817 /** Checks if the file name is reserved in InnoDB. Currently
1818 redo log file names from the old redo format (ib_logfile*)
1819 are reserved. There is no need to reserve file names from the
1820 newer redo formats, because they start with '#'.
1821 @return true if the name is reserved
1822 @param[in] hton handlerton of InnoDB
1823 @param[in] name Name of the database */
1824 static bool innobase_check_reserved_file_name(handlerton *hton,
1825 const char *name);
1826 /** Check tablespace name validity.
1827 @param[in] ts_cmd whether this is tablespace DDL or not
1828 @param[in] name name to check
1829 @retval false invalid name
1830 @retval true valid name */
1831 static bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd,
1832 const char *name);
1833
1834 /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces.
1835 @param[in] hton Handlerton of InnoDB
1836 @param[in] thd Connection
1837 @param[in] alter_info Describes the command and how to do it.
1838 @param[in] old_ts_def Old version of dd::Tablespace object for the
1839 tablespace.
1840 @param[in,out] new_ts_def New version of dd::Tablespace object for the
1841 tablespace. Can be adjusted by SE. Changes will be persisted in the
1842 data-dictionary at statement commit.
1843 @return MySQL error code*/
1844 static int innobase_alter_tablespace(handlerton *hton, THD *thd,
1845 st_alter_tablespace *alter_info,
1846 const dd::Tablespace *old_ts_def,
1847 dd::Tablespace *new_ts_def);
1848
1849 /**
1850 Get tablespace datafile name extension.
1851 */
1852 static const char *innobase_get_tablespace_filename_ext();
1853
1854 /** Free tablespace resources. */
1855 10407 static void innodb_space_shutdown() {
1856
1/2
✓ Branch 0 taken 10407 times.
✗ Branch 1 not taken.
10407 DBUG_TRACE;
1857
1858
1/2
✓ Branch 0 taken 10407 times.
✗ Branch 1 not taken.
10407 srv_sys_space.shutdown();
1859
2/2
✓ Branch 0 taken 10306 times.
✓ Branch 1 taken 101 times.
10407 if (srv_tmp_space.get_sanity_check_status()) {
1860
1/2
✓ Branch 0 taken 10306 times.
✗ Branch 1 not taken.
10306 fil_space_close(srv_tmp_space.space_id());
1861
1/2
✓ Branch 0 taken 10306 times.
✗ Branch 1 not taken.
10306 srv_tmp_space.delete_files();
1862 }
1863
1/2
✓ Branch 0 taken 10407 times.
✗ Branch 1 not taken.
10407 srv_tmp_space.shutdown();
1864 10407 }
1865
1866 /** Shut down InnoDB after the Global Data Dictionary has been shut down.
1867 @see innodb_pre_dd_shutdown()
1868 @retval 0 always */
1869 10400 static int innodb_shutdown(handlerton *, ha_panic_function) {
1870
1/2
✓ Branch 0 taken 10400 times.
✗ Branch 1 not taken.
10400 DBUG_TRACE;
1871
1872
2/2
✓ Branch 0 taken 10303 times.
✓ Branch 1 taken 97 times.
10400 if (innodb_inited) {
1873
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 log_pfs_delete_tables();
1874
1875 10303 innodb_inited = false;
1876 10303 ut::delete_(innobase_open_tables);
1877 10303 innobase_open_tables = nullptr;
1878
1879
2/2
✓ Branch 0 taken 10327 times.
✓ Branch 1 taken 10303 times.
20630 for (auto file : innobase_sys_files) {
1880 10327 ut::delete_(file);
1881 }
1882 10303 innobase_sys_files.clear();
1883
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 innobase_sys_files.shrink_to_fit();
1884
1885
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 mutex_free(&master_key_id_mutex);
1886
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 srv_shutdown();
1887
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 innodb_space_shutdown();
1888
1889
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 mysql_mutex_destroy(&innobase_share_mutex);
1890
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 mysql_mutex_destroy(&commit_cond_m);
1891
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 mysql_cond_destroy(&commit_cond);
1892
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 mysql_mutex_destroy(&resume_encryption_cond_m);
1893
1/2
✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
10303 mysql_cond_destroy(&resume_encryption_cond);
1894 }
1895
1896
1/2
✓ Branch 0 taken 10400 times.
✗ Branch 1 not taken.
10400 os_event_global_destroy();
1897
1898
1/2
✓ Branch 0 taken 10400 times.
✗ Branch 1 not taken.
10400 innobase::component_services::deinitialize_service_handles();
1899
1900 10400 return 0;
1901 10400 }
1902
1903 /** Shut down all InnoDB background tasks that may access
1904 the Global Data Dictionary, before the Global Data Dictionary
1905 and the rest of InnoDB have been shut down.
1906 @see dd::shutdown()
1907 @see innodb_shutdown() */
1908 10418 static void innodb_pre_dd_shutdown(handlerton *) {
1909
2/2
✓ Branch 0 taken 10321 times.
✓ Branch 1 taken 97 times.
10418 if (innodb_inited) {
1910 10321 srv_pre_dd_shutdown();
1911 }
1912 10400 }
1913
1914 /** Stores the current binlog coordinates in the trx system header.
1915 @param[in] hton InnoDB handlerton
1916 @param[in] thd MySQL thrad handle */
1917 static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept;
1918
1919 /** Creates an InnoDB transaction struct for the thd if it does not yet have
1920 one. Starts a new InnoDB transaction if a transaction is not yet started. And
1921 assigns a new snapshot for a consistent read if the transaction does not yet
1922 have one.
1923 @return 0 */
1924 static int innobase_start_trx_and_assign_read_view(
1925 handlerton *hton, /* in: InnoDB handlerton */
1926 THD *thd); /* in: MySQL thread handle of the
1927 user for whom the transaction should
1928 be committed */
1929
1930 /** Creates an InnoDB transaction struct for the thd if it does not
1931 yet have one. Starts a new InnoDB transaction if a transaction is not
1932 yet started. And clones snapshot for a consistent read from another
1933 session, if it has one.
1934 @param[in] hton InnoDB handlerton
1935 @param[in] thd MySQL thread handle of the user for whom the
1936 transaction should be committed
1937 @param[in] from_thd MySQL thread handle of the user session from
1938 which the consistent read should be cloned
1939 @return 0 */
1940 static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd,
1941 THD *from_thd);
1942
1943 /** Flush InnoDB redo logs to the file system.
1944 @param[in] hton InnoDB handlerton
1945 @param[in] binlog_group_flush true if we got invoked by binlog
1946 group commit during flush stage, false in other cases.
1947 @return false */
1948 static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush);
1949
1950 /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the
1951 InnoDB Monitor to the client.
1952 @param[in] hton the innodb handlerton
1953 @param[in] thd the MySQL query thread of the caller
1954 @param[in] stat_print print function
1955 @return 0 on success */
1956 static int innodb_show_status(handlerton *hton, THD *thd,
1957 stat_print_fn *stat_print);
1958
1959 /** Implements Log_resource lock.
1960 @param[in] hton the innodb handlerton
1961 @return false on success */
1962 static bool innobase_lock_hton_log(handlerton *hton);
1963
1964 /** Implements Log_resource unlock.
1965 @param[in] hton the innodb handlerton
1966 @return false on success */
1967 static bool innobase_unlock_hton_log(handlerton *hton);
1968
1969 /** Implements Log_resource collect_info.
1970 @param[in] hton the innodb handlerton
1971 @param[in] json the JSON dom to receive the log info
1972 @return false on success */
1973 static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json);
1974
1975 /** Return 0 on success and non-zero on failure. Note: the bool return type
1976 seems to be abused here, should be an int.
1977 @param[in] hton the innodb handlerton
1978 @param[in] thd the MySQL query thread of the caller
1979 @param[in] stat_print print function
1980 @param[in] stat_type status to show */
1981 static bool innobase_show_status(handlerton *hton, THD *thd,
1982 stat_print_fn *stat_print,
1983 enum ha_stat_type stat_type);
1984
1985 /** Parse and enable InnoDB monitor counters during server startup.
1986 User can enable monitor counters/groups by specifying
1987 "loose-innodb_monitor_enable = monitor_name1;monitor_name2..."
1988 in server configuration file or at the command line. */
1989 static void innodb_enable_monitor_at_startup(
1990 char *str); /*!< in: monitor counter enable list */
1991
1992 /** Fill handlerton based INFORMATION_SCHEMA tables.
1993 @param[in] hton (unused) Handle to the handlerton structure
1994 @param[in] thd Thread/connection descriptor
1995 @param[in,out] tables Information Schema tables to fill
1996 @param[in] idx_cond (unused) Intended for conditional pushdown
1997 @param[in] idx Table id that indicates which I_S table to fill
1998 @return Operation status */
1999 4 static int innobase_fill_i_s_table(handlerton *hton [[maybe_unused]],
2000 THD *thd [[maybe_unused]],
2001 TABLE_LIST *tables [[maybe_unused]],
2002 Item *idx_cond [[maybe_unused]],
2003 enum_schema_tables idx) {
2004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(idx == SCH_TABLESPACES);
2005
2006 /** InnoDB does not implement I_S.TABLESPACES */
2007
2008 4 return (0);
2009 }
2010
2011 /** Store doc_id value into FTS_DOC_ID field
2012 @param[in,out] tbl table containing FULLTEXT index
2013 @param[in] doc_id FTS_DOC_ID value */
2014 134 static void innobase_fts_store_docid(TABLE *tbl, ulonglong doc_id) {
2015 134 my_bitmap_map *old_map = dbug_tmp_use_all_columns(tbl, tbl->write_set);
2016
2017 134 tbl->fts_doc_id_field->store(static_cast<longlong>(doc_id), true);
2018
2019 134 dbug_tmp_restore_column_map(tbl->write_set, old_map);
2020 134 }
2021
2022 /** Check for a valid value of innobase_commit_concurrency.
2023 @return 0 for valid innodb_commit_concurrency */
2024 17 static int innobase_commit_concurrency_validate(
2025 THD *, /*!< in: thread handle */
2026 SYS_VAR *, /*!< in: pointer to system
2027 variable */
2028 void *save, /*!< out: immediate result
2029 for update function */
2030 struct st_mysql_value *value) /*!< in: incoming string */
2031 {
2032 long long intbuf;
2033 ulong commit_concurrency;
2034
2035
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 DBUG_TRACE;
2036
2037
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if (value->val_int(value, &intbuf)) {
2038 /* The value is NULL. That is invalid. */
2039 return 1;
2040 }
2041
2042 17 *reinterpret_cast<ulong *>(save) = commit_concurrency =
2043 17 static_cast<ulong>(intbuf);
2044
2045 /* Allow the value to be updated, as long as it remains zero
2046 or nonzero. */
2047 17 return !(!commit_concurrency == !innobase_commit_concurrency);
2048 17 }
2049
2050 /** Function for constructing an InnoDB table handler instance.
2051 @param[in,out] hton handlerton for InnoDB
2052 @param[in] table MySQL table
2053 @param[in] partitioned Indicates whether table is partitioned
2054 @param[in] mem_root memory context */
2055 10196980 static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table,
2056 bool partitioned, MEM_ROOT *mem_root) {
2057
2/2
✓ Branch 0 taken 69535 times.
✓ Branch 1 taken 10127445 times.
10196980 if (partitioned) {
2058
2/4
✓ Branch 0 taken 69535 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69535 times.
✗ Branch 3 not taken.
69535 ha_innopart *file = new (mem_root) ha_innopart(hton, table);
2059
3/6
✓ Branch 0 taken 69535 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69535 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 69535 times.
69535 if (file && file->init_partitioning(mem_root)) {
2060 destroy(file);
2061 return (nullptr);
2062 }
2063 69535 return (file);
2064 }
2065
2066
2/4
✓ Branch 0 taken 10127466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10127468 times.
✗ Branch 3 not taken.
10127445 return (new (mem_root) ha_innobase(hton, table));
2067 }
2068
2069 /* General functions */
2070
2071 /** Returns true if the thread is the replication thread on the slave
2072 server. Used in srv_conc_enter_innodb() to determine if the thread
2073 should be allowed to enter InnoDB - the replication thread is treated
2074 differently than other threads. Also used in
2075 srv_conc_force_exit_innodb().
2076 @return true if thd is the replication thread */
2077 232577 bool thd_is_replication_slave_thread(THD *thd) /*!< in: thread handle */
2078 {
2079
3/4
✓ Branch 0 taken 232580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 539 times.
✓ Branch 3 taken 232041 times.
232577 return thd != nullptr && thd_slave_thread(thd);
2080 }
2081
2082 /** Gets information on the durability property requested by thread.
2083 Used when writing either a prepare or commit record to the log
2084 buffer. @return the durability property. */
2085 7011527 enum durability_properties thd_requested_durability(
2086 const THD *thd) /*!< in: thread handle */
2087 {
2088 7011527 return (thd_get_durability_property(thd));
2089 }
2090
2091 /** Returns true if transaction should be flagged as read-only.
2092 @return true if the thd is marked as read-only */
2093 17653923 bool thd_trx_is_read_only(THD *thd) /*!< in: thread handle */
2094 {
2095
4/4
✓ Branch 0 taken 17458018 times.
✓ Branch 1 taken 195905 times.
✓ Branch 2 taken 12158071 times.
✓ Branch 3 taken 5300244 times.
17653923 return (thd != nullptr && thd_tx_is_read_only(thd));
2096 }
2097
2098 /**
2099 Check if the transaction can be rolled back
2100 @param[in] requestor Session requesting the lock
2101 @param[in] holder Session that holds the lock
2102 @return the session that will be rolled back, null don't care */
2103
2104 1 THD *thd_trx_arbitrate(THD *requestor, THD *holder) {
2105 /* Non-user (thd==0) transactions by default can't rollback, in
2106 practice DDL transactions should never rollback and that's because
2107 they should never wait on table/record locks either */
2108
2109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 ut_a(holder != nullptr);
2110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 ut_a(holder != requestor);
2111
2112 1 THD *victim = thd_tx_arbitrate(requestor, holder);
2113
2114
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 ut_a(victim == nullptr || victim == requestor || victim == holder);
2115
2116 1 return (victim);
2117 }
2118
2119 /**
2120 @param[in] thd Session to check
2121 @return the priority */
2122
2123 357106772 int thd_trx_priority(THD *thd) {
2124
1/2
✓ Branch 0 taken 357107036 times.
✗ Branch 1 not taken.
357106772 return (thd == nullptr ? 0 : thd_tx_priority(thd));
2125 }
2126
2127 /** Check if the transaction is an auto-commit transaction. true also
2128 implies that it is a SELECT (read-only) transaction.
2129 @return true if the transaction is an auto commit read-only transaction. */
2130 19803689 bool thd_trx_is_auto_commit(THD *thd) /*!< in: thread handle, can be NULL */
2131 {
2132 17458677 return thd != nullptr &&
2133
4/4
✓ Branch 0 taken 17458785 times.
✓ Branch 1 taken 2344904 times.
✓ Branch 2 taken 16350978 times.
✓ Branch 3 taken 1107699 times.
36154704 !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) &&
2134
2/2
✓ Branch 0 taken 12746471 times.
✓ Branch 1 taken 3604544 times.
36154596 thd_is_query_block(thd);
2135 }
2136
2137 extern "C" long long thd_start_time(const THD *thd);
2138
2139 17457925 std::chrono::system_clock::time_point thd_start_time(THD *) {
2140 // FIXME: This function should be added to the server code.
2141 // return(thd_start_time(thd));
2142 17457925 return std::chrono::system_clock::now();
2143 }
2144
2145 /** Enter InnoDB engine after checking the max number of user threads
2146 allowed, else the thread is put into sleep.
2147 @param[in,out] prebuilt row prebuilt handler
2148 @return InnoDB error code. */
2149 453762881 static inline dberr_t innobase_srv_conc_enter_innodb(row_prebuilt_t *prebuilt) {
2150 /* We rely on server to do external_lock(F_UNLCK) to reset the
2151 srv_conc.n_active counter. */
2152
2/2
✓ Branch 0 taken 214641393 times.
✓ Branch 1 taken 239122971 times.
453762881 if (prebuilt->skip_concurrency_ticket()) {
2153 214641393 return DB_SUCCESS;
2154 }
2155
2156 239122971 dberr_t err = DB_SUCCESS;
2157 239122971 trx_t *trx = prebuilt->trx;
2158
2159
2/2
✓ Branch 0 taken 30100 times.
✓ Branch 1 taken 239092871 times.
239122971 if (srv_thread_concurrency) {
2160
2/2
✓ Branch 0 taken 28220 times.
✓ Branch 1 taken 1880 times.
30100 if (trx->n_tickets_to_enter_innodb > 0) {
2161 /* If trx has 'free tickets' to enter the engine left,
2162 then use one such ticket */
2163
2164 28220 --trx->n_tickets_to_enter_innodb;
2165
2166
2/4
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1879 times.
3759 } else if (trx->mysql_thd != nullptr &&
2167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1879 times.
1880 thd_is_replication_slave_thread(trx->mysql_thd)) {
2168 ut::wait_for(
2169 [&]() {
2170 return srv_conc_get_active_threads() <
2171 (int32_t)srv_thread_concurrency;
2172 },
2173 get_srv_replication_delay());
2174
2175 } else {
2176 1879 err = srv_conc_enter_innodb(prebuilt);
2177 }
2178 }
2179
2180 239122971 return err;
2181 }
2182
2183 /** Note that the thread wants to leave InnoDB only if it doesn't have
2184 any spare tickets.
2185 @param[in,out] prebuilt row prebuilt handler */
2186 453764615 static inline void innobase_srv_conc_exit_innodb(row_prebuilt_t *prebuilt) {
2187 /* We rely on server to do external_lock(F_UNLCK) to reset the
2188 srv_conc.n_active counter. */
2189
3/4
✓ Branch 0 taken 453764889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214641431 times.
✓ Branch 3 taken 239123458 times.
453764615 if (prebuilt->skip_concurrency_ticket()) {
2190 214641431 return;
2191 }
2192
2193 239123458 trx_t *trx = prebuilt->trx;
2194 #ifdef UNIV_DEBUG
2195 239123458 btrsea_sync_check check(trx->has_search_latch);
2196
2197
2/4
✓ Branch 0 taken 239123471 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 239123445 times.
239123346 ut_ad(!sync_check_iterate(check));
2198 #endif /* UNIV_DEBUG */
2199
2200 /* This is to avoid making an unnecessary function call. */
2201
2/2
✓ Branch 0 taken 30098 times.
✓ Branch 1 taken 239093347 times.
239123445 if (trx->declared_to_be_inside_innodb &&
2202
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 30095 times.
30098 trx->n_tickets_to_enter_innodb == 0) {
2203
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 srv_conc_force_exit_innodb(trx);
2204 }
2205 239123445 }
2206
2207 /** Force a thread to leave InnoDB even if it has spare tickets. */
2208 171070329 static inline void innobase_srv_conc_force_exit_innodb(
2209 trx_t *trx) /*!< in: transaction handle */
2210 {
2211 #ifdef UNIV_DEBUG
2212 171070329 btrsea_sync_check check(trx->has_search_latch);
2213
2214
2/4
✓ Branch 0 taken 171070605 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 171070558 times.
171070505 ut_ad(!sync_check_iterate(check));
2215 #endif /* UNIV_DEBUG */
2216
2217 /* This is to avoid making an unnecessary function call. */
2218
2/2
✓ Branch 0 taken 1875 times.
✓ Branch 1 taken 171068683 times.
171070558 if (trx->declared_to_be_inside_innodb) {
2219
1/2
✓ Branch 0 taken 1875 times.
✗ Branch 1 not taken.
1875 srv_conc_force_exit_innodb(trx);
2220 }
2221 171070558 }
2222
2223 /** Returns the NUL terminated value of glob_hostname.
2224 @return pointer to glob_hostname. */
2225 703 const char *server_get_hostname() { return (glob_hostname); }
2226
2227 /** Returns true if the transaction this thread is processing has edited
2228 non-transactional tables. Used by the deadlock detector when deciding
2229 which transaction to rollback in case of a deadlock - we try to avoid
2230 rolling back transactions that have edited non-transactional tables.
2231 @return true if non-transactional tables have been edited */
2232 376 bool thd_has_edited_nontrans_tables(THD *thd) /*!< in: thread handle */
2233 {
2234 376 return thd_non_transactional_update(thd);
2235 }
2236
2237 /** Returns true if the thread is executing a SELECT statement.
2238 @return true if thd is executing SELECT */
2239 16612932 bool thd_is_query_block(const THD *thd) /*!< in: thread handle */
2240 {
2241 16612932 return thd_sql_command(thd) == SQLCOM_SELECT;
2242 }
2243
2244 /** Checks sys_vars and determines if allocator should mark
2245 large memory segments with MADV_DONTDUMP
2246 @return true iff @@global.core_file AND
2247 NOT @@global.innodb_buffer_pool_in_core_file */
2248 11994 bool innobase_should_madvise_buf_pool() {
2249
4/4
✓ Branch 0 taken 11563 times.
✓ Branch 1 taken 431 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 11559 times.
11994 return (test_flags & TEST_CORE_ON_SIGNAL) && !srv_buffer_pool_in_core_file;
2250 }
2251
2252 /** Make sure that core file will not be generated, as generating a core file
2253 might violate our promise to not dump buffer pool data, and/or might dump not
2254 the expected memory pages due to failure in using madvise */
2255 void innobase_disable_core_dump() {
2256 /* TODO: There is a race condition here, as test_flags is not an atomic<>
2257 and there might be multiple threads calling this function
2258 in parallel (once for each buffer pool thread).
2259 One approach would be to use a loop with os_compare_and_swap_ulint
2260 unfortunately test_flags is defined as uint, not ulint, and we don't
2261 have nice portable function for dealing with uint in InnoDB.
2262 Moreover that would only prevent problems with mangled bits, but not
2263 help at all with that some other thread might be reading test_flags
2264 and making decisions based on observed value while we are changing it.
2265 The good news is that all these threads try to do the same thing: clear the
2266 same bit. So this happens to work.
2267 */
2268
2269 test_flags &= ~TEST_CORE_ON_SIGNAL;
2270 }
2271
2272 238918 std::chrono::seconds thd_lock_wait_timeout(THD *thd) {
2273 /* According to <mysql/plugin.h>, passing thd == NULL
2274 returns the global value of the session variable. */
2275 238918 return std::chrono::seconds{THDVAR(thd, lock_wait_timeout)};
2276 }
2277
2278 /** Is FT ignore stopwords variable set.
2279 @param thd Thread object
2280 @return true if ft_ignore_stopwords is set, false otherwise. */
2281 17524614 bool thd_has_ft_ignore_stopwords(THD *thd) noexcept {
2282 17524614 return (THDVAR(thd, ft_ignore_stopwords));
2283 }
2284
2285 41613 void thd_set_lock_wait_time(THD *thd,
2286 std::chrono::steady_clock::duration value) {
2287
1/2
✓ Branch 0 taken 41613 times.
✗ Branch 1 not taken.
41613 if (thd) {
2288
1/2
✓ Branch 0 taken 41613 times.
✗ Branch 1 not taken.
41613 thd_storage_lock_wait(
2289 thd,
2290 83226 std::chrono::duration_cast<std::chrono::microseconds>(value).count());
2291 }
2292 41613 }
2293
2294 81815 const char *thd_innodb_tmpdir(THD *thd) {
2295 #ifdef UNIV_DEBUG
2296
2/2
✓ Branch 0 taken 81761 times.
✓ Branch 1 taken 54 times.
81815 if (thd != nullptr) {
2297
1/2
✓ Branch 0 taken 81761 times.
✗ Branch 1 not taken.
81761 auto trx = thd_to_trx(thd);
2298
2299 81761 btrsea_sync_check check(trx->has_search_latch);
2300
2301
2/4
✓ Branch 0 taken 81761 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81761 times.
81761 ut_ad(!sync_check_iterate(check));
2302 81761 }
2303 #endif /* UNIV_DEBUG */
2304
2305 81815 const char *tmp_dir = THDVAR(thd, tmpdir);
2306
2307
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 81798 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
81815 if (tmp_dir != nullptr && *tmp_dir == '\0') {
2308 tmp_dir = nullptr;
2309 }
2310
2311 81815 return tmp_dir;
2312 }
2313
2314 /** Obtain the private handler of InnoDB session specific data.
2315 @param[in,out] thd MySQL thread handler.
2316 @return reference to private handler */
2317
2318 3475226278 [[nodiscard]] innodb_session_t *&thd_to_innodb_session(THD *thd) {
2319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3475226278 times.
3475226278 assert(innodb_hton_ptr->slot != HA_SLOT_UNDEF);
2320
2321 innodb_session_t *&innodb_session =
2322 3475226278 *(innodb_session_t **)thd_ha_data(thd, innodb_hton_ptr);
2323
2324
2/2
✓ Branch 0 taken 3457212037 times.
✓ Branch 1 taken 18021504 times.
3475233541 if (innodb_session != nullptr) {
2325 3457212037 return (innodb_session);
2326 }
2327
2328 18021504 innodb_session = ut::new_withkey<innodb_session_t>(UT_NEW_THIS_FILE_PSI_KEY);
2329 18022887 return (innodb_session);
2330 }
2331
2332 /** Obtain the InnoDB transaction of a MySQL thread.
2333 @param[in,out] thd MySQL thread handler.
2334 @return reference to transaction pointer */
2335
2336 3360873537 [[nodiscard]] trx_t *&thd_to_trx(THD *thd) {
2337 3360873537 innodb_session_t *&innodb_session = thd_to_innodb_session(thd);
2338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3360878926 times.
3360882940 ut_ad(innodb_session != nullptr);
2339
2340 3360878926 return (innodb_session->m_trx);
2341 }
2342
2343 76062 ulong thd_parallel_read_threads(THD *thd) {
2344 76062 return THDVAR(thd, parallel_read_threads);
2345 }
2346
2347 35474 ulong thd_ddl_buffer_size(THD *thd) { return THDVAR(thd, ddl_buffer_size); }
2348
2349 35474 size_t thd_ddl_threads(THD *thd) noexcept { return THDVAR(thd, ddl_threads); }
2350
2351 /** Check if statement is of type INSERT .... SELECT that involves
2352 use of intrinsic tables.
2353 @param[in] user_thd thread handler
2354 @return true if INSERT .... SELECT statement. */
2355 71154200 static inline bool thd_is_ins_sel_stmt(THD *user_thd) {
2356 /* If the session involves use of intrinsic table
2357 and it is trying to fetch the result from non-temporary tables
2358 it indicates "insert .... select" statement. For non-temporary
2359 table this is verifed using the locked tables count but for
2360 intrinsic table as external_lock is not invoked this count is
2361 not updated.
2362
2363 Why is this needed ?
2364 Use of AHI is blocked if statement is insert .... select statement. */
2365 71154200 innodb_session_t *innodb_priv = thd_to_innodb_session(user_thd);
2366 71154450 return (innodb_priv->count_register_table_handler() > 0 ? true : false);
2367 }
2368
2369 /** Add the table handler to thread cache.
2370 Obtain the InnoDB transaction of a MySQL thread.
2371 @param[in,out] table table handler
2372 @param[in,out] heap heap for allocating system columns.
2373 @param[in,out] thd MySQL thread handler */
2374 182644 static inline void add_table_to_thread_cache(dict_table_t *table,
2375 mem_heap_t *heap, THD *thd) {
2376 182644 dict_table_add_system_columns(table, heap);
2377
2378 182644 dict_table_set_big_rows(table);
2379
2380 182644 innodb_session_t *&priv = thd_to_innodb_session(thd);
2381 182644 priv->register_table_handler(table->name.m_name, table);
2382 182644 }
2383
2384 /** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
2385 time calls srv_active_wake_master_thread. This function should be used
2386 when a single database operation may introduce a small need for
2387 server utility activity, like checkpointing. */
2388 65525682 inline void innobase_active_small(void) {
2389 65525682 innobase_active_counter++;
2390
2391
2/2
✓ Branch 0 taken 2041740 times.
✓ Branch 1 taken 63483942 times.
65525682 if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
2392 2041740 srv_active_wake_master_thread();
2393 }
2394 65525682 }
2395
2396 /** Converts an InnoDB error code to a MySQL error code.
2397 Also tells to MySQL about a possible transaction rollback inside InnoDB caused
2398 by a lock wait timeout or a deadlock.
2399 @param[in] error InnoDB error code.
2400 @param[in] flags InnoDB table flags or 0.
2401 @param[in] thd MySQL thread or NULL.
2402 @return MySQL error code */
2403 90370017 int convert_error_code_to_mysql(dberr_t error, uint32_t flags, THD *thd) {
2404
32/48
✓ Branch 0 taken 89728294 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 255 times.
✓ Branch 5 taken 639911 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 493 times.
✓ Branch 11 taken 404 times.
✓ Branch 12 taken 87 times.
✓ Branch 13 taken 85 times.
✓ Branch 14 taken 10 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 22 times.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 26 times.
✓ Branch 24 taken 34 times.
✓ Branch 25 taken 11 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✓ Branch 29 taken 6 times.
✓ Branch 30 taken 10 times.
✓ Branch 31 taken 213 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 15 times.
✓ Branch 34 taken 10 times.
✓ Branch 35 taken 8 times.
✓ Branch 36 taken 26 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 1 times.
✓ Branch 43 taken 55 times.
✓ Branch 44 taken 3 times.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
90370017 switch (error) {
2405 89728294 case DB_SUCCESS:
2406 89728294 return (0);
2407
2408 39 case DB_INTERRUPTED:
2409
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 38 times.
39 thd_set_kill_status(thd != nullptr ? thd : current_thd);
2410 38 return (HA_ERR_GENERIC);
2411
2412 1 case DB_FOREIGN_EXCEED_MAX_CASCADE:
2413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 ut_ad(thd);
2414 1 my_error(ER_FK_DEPTH_EXCEEDED, MYF(0), FK_MAX_CASCADE_DEL);
2415 1 return (HA_ERR_FK_DEPTH_EXCEEDED);
2416
2417 case DB_CANT_CREATE_GEOMETRY_OBJECT:
2418 my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0));
2419 return (HA_ERR_NULL_IN_SPATIAL);
2420
2421 255 case DB_ERROR:
2422 default:
2423 255 return (HA_ERR_GENERIC); /* unspecified error */
2424
2425 639911 case DB_DUPLICATE_KEY:
2426 /* Be cautious with returning this error, since
2427 mysql could re-enter the storage layer to get
2428 duplicated key info, the operation requires a
2429 valid table handle and/or transaction information,
2430 which might not always be available in the error
2431 handling stage. */
2432 639911 return (HA_ERR_FOUND_DUPP_KEY);
2433
2434 4 case DB_READ_ONLY:
2435
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (srv_force_recovery) {
2436 4 return (HA_ERR_INNODB_FORCED_RECOVERY);
2437 }
2438 return (HA_ERR_TABLE_READONLY);
2439
2440 3 case DB_FOREIGN_DUPLICATE_KEY:
2441 3 return (HA_ERR_FOREIGN_DUPLICATE_KEY);
2442
2443 case DB_MISSING_HISTORY:
2444 return (HA_ERR_TABLE_DEF_CHANGED);
2445
2446 case DB_RECORD_NOT_FOUND:
2447 return (HA_ERR_NO_ACTIVE_RECORD);
2448
2449 493 case DB_FORCED_ABORT:
2450 case DB_DEADLOCK:
2451 /* Since we rolled back the whole transaction, we must
2452 tell it also to MySQL so that MySQL knows to empty the
2453 cached binlog for this transaction */
2454
2455
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 if (thd != nullptr) {
2456 493 thd_mark_transaction_to_rollback(thd, 1);
2457 }
2458
2459 493 return (HA_ERR_LOCK_DEADLOCK);
2460
2461 404 case DB_LOCK_WAIT_TIMEOUT:
2462 /* Starting from 5.0.13, we let MySQL just roll back the
2463 latest SQL statement in a lock wait timeout. Previously, we
2464 rolled back the whole transaction. */
2465
2466
1/2
✓ Branch 0 taken 404 times.
✗ Branch 1 not taken.
404 if (thd) {
2467 404 thd_mark_transaction_to_rollback(thd, (int)row_rollback_on_timeout);
2468 }
2469
2470 405 return (HA_ERR_LOCK_WAIT_TIMEOUT);
2471
2472 87 case DB_NO_REFERENCED_ROW:
2473 87 return (HA_ERR_NO_REFERENCED_ROW);
2474
2475 85 case DB_ROW_IS_REFERENCED:
2476 85 return (HA_ERR_ROW_IS_REFERENCED);
2477
2478 10 case DB_NO_FK_ON_S_BASE_COL:
2479 case DB_CANNOT_ADD_CONSTRAINT:
2480 case DB_CHILD_NO_INDEX:
2481 case DB_PARENT_NO_INDEX:
2482 10 return (HA_ERR_CANNOT_ADD_FOREIGN);
2483
2484 3 case DB_CANNOT_DROP_CONSTRAINT:
2485
2486 3 return (HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
2487 misleading, a new MySQL error
2488 code should be introduced */
2489
2490 22 case DB_CORRUPTION:
2491 22 return (HA_ERR_CRASHED);
2492
2493 8 case DB_OUT_OF_FILE_SPACE:
2494 8 return (HA_ERR_RECORD_FILE_FULL);
2495
2496 case DB_OUT_OF_DISK_SPACE:
2497 return (HA_ERR_DISK_FULL_NOWAIT);
2498
2499 case DB_TEMP_FILE_WRITE_FAIL:
2500 return (HA_ERR_TEMP_FILE_WRITE_FAILURE);
2501
2502 case DB_TABLE_IN_FK_CHECK:
2503 return (HA_ERR_TABLE_IN_FK_CHECK);
2504
2505 case DB_TABLE_IS_BEING_USED:
2506 return (HA_ERR_WRONG_COMMAND);
2507
2508 2 case DB_TABLE_NOT_FOUND:
2509 2 return (HA_ERR_NO_SUCH_TABLE);
2510
2511 26 case DB_TABLESPACE_NOT_FOUND:
2512 26 return (HA_ERR_TABLESPACE_MISSING);
2513
2514 34 case DB_TOO_BIG_RECORD: {
2515 /* If prefix is true then a 768-byte prefix is stored
2516 locally for BLOB fields. Refer to dict_table_get_format().
2517 We limit max record size to 16k for 64k page size. */
2518 34 bool prefix = !DICT_TF_HAS_ATOMIC_BLOBS(flags);
2519
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 17 times.
68 my_printf_error(
2520 ER_TOO_BIG_ROWSIZE,
2521 "Row size too large (> %lu). Changing some columns"
2522 " to TEXT or BLOB %smay help. In current row"
2523 " format, BLOB prefix of %d bytes is stored inline.",
2524 MYF(0),
2525
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 srv_page_size == UNIV_PAGE_SIZE_MAX
2526 ? REC_MAX_DATA_SIZE - 1
2527 34 : page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2,
2528 prefix ? "or using ROW_FORMAT=DYNAMIC or"
2529 " ROW_FORMAT=COMPRESSED "
2530 : "",
2531 prefix ? DICT_MAX_FIXED_COL_LEN : 0);
2532 34 return (HA_ERR_TOO_BIG_ROW);
2533 }
2534
2535 11 case DB_TOO_BIG_INDEX_COL:
2536 11 my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
2537 DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
2538 11 return (HA_ERR_INDEX_COL_TOO_LONG);
2539
2540 case DB_NO_SAVEPOINT:
2541 return (HA_ERR_NO_SAVEPOINT);
2542
2543 case DB_LOCK_TABLE_FULL:
2544 /* Since we rolled back the whole transaction, we must
2545 tell it also to MySQL so that MySQL knows to empty the
2546 cached binlog for this transaction */
2547
2548 if (thd) {
2549 thd_mark_transaction_to_rollback(thd, 1);
2550 }
2551
2552 return (HA_ERR_LOCK_TABLE_FULL);
2553
2554 3 case DB_FTS_INVALID_DOCID:
2555 3 return (HA_FTS_INVALID_DOCID);
2556 6 case DB_FTS_EXCEED_RESULT_CACHE_LIMIT:
2557 6 return (HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT);
2558 10 case DB_TOO_MANY_CONCURRENT_TRXS:
2559 10 return (HA_ERR_TOO_MANY_CONCURRENT_TRXS);
2560 213 case DB_UNSUPPORTED:
2561 213 return (HA_ERR_UNSUPPORTED);
2562 case DB_INDEX_CORRUPT:
2563 return (HA_ERR_INDEX_CORRUPT);
2564 15 case DB_UNDO_RECORD_TOO_BIG:
2565 15 return (HA_ERR_UNDO_REC_TOO_BIG);
2566 10 case DB_OUT_OF_MEMORY:
2567 10 return (HA_ERR_OUT_OF_MEM);
2568 8 case DB_TABLESPACE_EXISTS:
2569 8 return (HA_ERR_TABLESPACE_EXISTS);
2570 26 case DB_TABLESPACE_DELETED:
2571 26 return (HA_ERR_TABLESPACE_MISSING);
2572 case DB_IDENTIFIER_TOO_LONG:
2573 return (HA_ERR_INTERNAL_ERROR);
2574 case DB_TOO_LONG_PATH:
2575 return (HA_ERR_TOO_LONG_PATH);
2576 1 case DB_TABLE_CORRUPT:
2577 1 return (HA_ERR_TABLE_CORRUPT);
2578 case DB_FTS_TOO_MANY_WORDS_IN_PHRASE:
2579 return (HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE);
2580 case DB_WRONG_FILE_NAME:
2581 return (HA_ERR_WRONG_FILE_NAME);
2582 1 case DB_COMPUTE_VALUE_FAILED:
2583 1 return (HA_ERR_COMPUTE_FAILED);
2584 55 case DB_LOCK_NOWAIT:
2585 55 my_error(ER_LOCK_NOWAIT, MYF(0));
2586 55 return (HA_ERR_NO_WAIT_LOCK);
2587 3 case DB_NO_SESSION_TEMP:
2588 3 return (HA_ERR_NO_SESSION_TEMP);
2589 1 case DB_BTREE_LEVEL_LIMIT_EXCEEDED:
2590 1 return (HA_ERR_INTERNAL_ERROR);
2591 case DB_FTS_TOO_MANY_NESTED_EXP:
2592 return (HA_ERR_FTS_TOO_MANY_NESTED_EXP);
2593 case DB_IO_NO_PUNCH_HOLE:
2594 case DB_IO_NO_PUNCH_HOLE_FS:
2595 case DB_IO_NO_PUNCH_HOLE_TABLESPACE:
2596 return HA_ERR_UNSUPPORTED;
2597 }
2598 }
2599
2600 /** Prints info of a THD object (== user session thread) to the given file. */
2601 572 void innobase_mysql_print_thd(
2602 FILE *f, /*!< in: output stream */
2603 THD *thd, /*!< in: MySQL THD object */
2604 uint max_query_len) /*!< in: max query length to print, or 0 to
2605 use the default max length */
2606 {
2607 char buffer[1024];
2608
2609
2/4
✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 572 times.
✗ Branch 3 not taken.
572 fputs(thd_security_context(thd, buffer, sizeof buffer, max_query_len), f);
2610
1/2
✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
572 putc('\n', f);
2611 572 }
2612
2613 /** Get the error message format string.
2614 @return the format string or 0 if not found. */
2615 8336 const char *innobase_get_err_msg(int error_code) /*!< in: MySQL error code */
2616 {
2617 8336 return (my_get_err_msg(error_code));
2618 }
2619
2620 /** Get the variable length bounds of the given character set.
2621 @param[in] cset Mysql charset-collation code
2622 @param[out] mbminlen Minimum length of a char (in bytes)
2623 @param[out] mbmaxlen Maximum length of a char (in bytes) */
2624 66664007 void innobase_get_cset_width(ulint cset, ulint *mbminlen, ulint *mbmaxlen) {
2625 CHARSET_INFO *cs;
2626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66657236 times.
66664007 ut_ad(cset <= MAX_CHAR_COLL_NUM);
2627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66644561 times.
66657236 ut_ad(mbminlen);
2628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66641533 times.
66644561 ut_ad(mbmaxlen);
2629
2630 66641533 cs = all_charsets[cset];
2631
2/2
✓ Branch 0 taken 16452410 times.
✓ Branch 1 taken 50189123 times.
66641533 if (cs) {
2632 16452410 *mbminlen = cs->mbminlen;
2633 16452410 *mbmaxlen = cs->mbmaxlen;
2634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16452408 times.
16452410 ut_ad(*mbminlen < DATA_MBMAX);
2635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16452417 times.
16452408 ut_ad(*mbmaxlen < DATA_MBMAX);
2636 } else {
2637 50189123 THD *thd = current_thd;
2638
2639
6/6
✓ Branch 0 taken 44204909 times.
✓ Branch 1 taken 5984985 times.
✓ Branch 2 taken 417512 times.
✓ Branch 3 taken 43787515 times.
✓ Branch 4 taken 417512 times.
✓ Branch 5 taken 49772500 times.
50189894 if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) {
2640 /* Fix bug#46256: allow tables to be dropped if the
2641 collation is not found, but issue a warning. */
2642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 417512 times.
417512 if (cset != 0) {
2643 log_errlog(ERROR_LEVEL, ER_INNODB_UNKNOWN_COLLATION);
2644 }
2645 } else {
2646
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49766888 times.
49772500 ut_a(cset == 0);
2647 }
2648
2649 50192922 *mbminlen = *mbmaxlen = 0;
2650 }
2651 66645339 }
2652
2653 /**********************************************************************
2654 Check if the length of the identifier exceeds the maximum allowed.
2655 return true when length of identifier is too long. */
2656 358 bool innobase_check_identifier_length(
2657 const char *id) /* in: FK identifier to check excluding the
2658 database portion. */
2659 {
2660 358 int well_formed_error = 0;
2661 358 CHARSET_INFO *cs = system_charset_info;
2662
1/2
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
358 DBUG_TRACE;
2663
2664
1/2
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
358 size_t len = cs->cset->well_formed_len(cs, id, id + strlen(id), NAME_CHAR_LEN,
2665 &well_formed_error);
2666
2667
2/4
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
358 if (well_formed_error || len != strlen(id)) {
2668 my_error(ER_TOO_LONG_IDENT, MYF(0), id);
2669 return true;
2670 }
2671 358 return false;
2672 358 }
2673 #endif /* !UNIV_HOTBACKUP */
2674
2675 /** Compares NUL-terminated UTF-8 strings case insensitively.
2676 @return 0 if a=b, <0 if a\<b, >1 if a>b */
2677 35786178 int innobase_strcasecmp(const char *a, /*!< in: first string to compare */
2678 const char *b) /*!< in: second string to compare */
2679 {
2680
2/2
✓ Branch 0 taken 1162202 times.
✓ Branch 1 taken 34623976 times.
35786178 if (!a) {
2681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1162202 times.
1162202 if (!b) {
2682 return (0);
2683 } else {
2684 1162202 return (-1);
2685 }
2686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34623976 times.
34623976 } else if (!b) {
2687 return (1);
2688 }
2689
2690 34623976 return (my_strcasecmp(system_charset_info, a, b));
2691 }
2692
2693 #ifndef UNIV_HOTBACKUP
2694 /** Compares NUL-terminated UTF-8 strings case insensitively. The
2695 second string contains wildcards.
2696 @return 0 if a match is found, 1 if not */
2697 23959 static int innobase_wildcasecmp(
2698 const char *a, /*!< in: string to compare */
2699 const char *b) /*!< in: wildcard string to compare */
2700 {
2701 23959 return (wild_case_compare(system_charset_info, a, b));
2702 }
2703 #endif /* !UNIV_HOTBACKUP */
2704
2705 /** Strip dir name from a full path name and return only the file name
2706 @param[in] path_name full path name
2707 @return file name or "null" if no file name */
2708 204 const char *innobase_basename(const char *path_name) {
2709 204 const char *name = base_name(path_name);
2710
2711
1/2
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
204 return ((name) ? name : "null");
2712 }
2713
2714 #ifndef UNIV_HOTBACKUP
2715
2716 /** Makes all characters in a NUL-terminated UTF-8 string lower case. */
2717 942673 void innobase_casedn_str(char *a) /*!< in/out: string to put in lower case */
2718 {
2719 942673 my_casedn_str(system_charset_info, a);
2720 942672 }
2721
2722 /** Makes all characters in a NUL-terminated UTF-8 path string lower case. */
2723 30 void innobase_casedn_path(char *a) /*!< in/out: string to put in lower case */
2724 {
2725 30 my_casedn_str(&my_charset_filename, a);
2726 30 }
2727
2728 /** Determines the connection character set.
2729 @return connection character set */
2730 61 const CHARSET_INFO *innobase_get_charset(
2731 THD *mysql_thd) /*!< in: MySQL thread handle */
2732 {
2733 61 return (thd_charset(mysql_thd));
2734 }
2735
2736 /** Determines the current SQL statement.
2737 Thread unsafe, can only be called from the thread owning the THD.
2738 @param[in] thd MySQL thread handle
2739 @param[out] length Length of the SQL statement
2740 @return SQL statement string */
2741 429023 const char *innobase_get_stmt_unsafe(THD *thd, size_t *length) {
2742 LEX_CSTRING stmt;
2743
2744
1/2
✓ Branch 0 taken 429023 times.
✗ Branch 1 not taken.
429023 stmt = thd_query_unsafe(thd);
2745 429023 *length = stmt.length;
2746 429023 return (stmt.str);
2747 }
2748
2749 /** Determines the current SQL statement.
2750 Thread safe, can be called from any thread as the string is copied
2751 into the provided buffer.
2752 @param[in] thd MySQL thread handle
2753 @param[out] buf Buffer containing SQL statement
2754 @param[in] buflen Length of provided buffer
2755 @return Length of the SQL statement */
2756 80 size_t innobase_get_stmt_safe(THD *thd, char *buf, size_t buflen) {
2757 80 return (thd_query_safe(thd, buf, buflen));
2758 }
2759
2760 /** Get the current setting of the table_def_size global parameter. We do
2761 a dirty read because for one there is no synchronization object and
2762 secondly there is little harm in doing so even if we get a torn read.
2763 @return value of table_def_size */
2764 552518 ulint innobase_get_table_cache_size(void) { return (table_def_size); }
2765
2766 /** Get the current setting of the lower_case_table_names global parameter from
2767 mysqld.cc. We do a dirty read because for one there is no synchronization
2768 object and secondly there is little harm in doing so even if we get a torn
2769 read.
2770 @return value of lower_case_table_names */
2771 27619861 ulint innobase_get_lower_case_table_names(void) {
2772 27619861 return (lower_case_table_names);
2773 }
2774
2775 18146 char *innobase_mysql_tmpdir() { return (mysql_tmpdir); }
2776
2777 77832 os_fd_t innobase_mysql_tmpfile(const char *path) {
2778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77833 times.
77832 DBUG_EXECUTE_IF("innobase_tmpfile_creation_failure", return (-1););
2779
2780 auto fd =
2781
2/2
✓ Branch 0 taken 11946 times.
✓ Branch 1 taken 65887 times.
77833 (path == nullptr) ? mysql_tmpfile("ib") : mysql_tmpfile_path(path, "ib");
2782
2783 77833 os_fd_t fd2{OS_FD_CLOSED};
2784
2785
2/2
✓ Branch 0 taken 77832 times.
✓ Branch 1 taken 1 times.
77833 if (fd >= 0) {
2786 /* Copy the file descriptor, so that the additional resources
2787 allocated by create_temp_file() can be freed by invoking
2788 my_close().
2789
2790 Because the file descriptor returned by this function
2791 will be passed to fdopen(), it will be closed by invoking
2792 fclose(), which in turn will invoke close() instead of
2793 my_close(). */
2794
2795 #ifdef _WIN32
2796 /* Note that on Windows, the integer returned by mysql_tmpfile
2797 has no relation to C runtime file descriptor. Here, we need
2798 to call my_get_osfhandle to get the HANDLE and then convert it
2799 to C runtime filedescriptor. */
2800 {
2801 HANDLE hDup;
2802
2803 auto hFile = my_get_osfhandle(fd);
2804
2805 auto bOK =
2806 DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(),
2807 &hDup, 0, false, DUPLICATE_SAME_ACCESS);
2808 if (bOK) {
2809 fd2 = _open_osfhandle((intptr_t)hDup, 0);
2810 } else {
2811 my_osmaperr(GetLastError());
2812 fd2 = OS_FD_CLOSED;
2813 }
2814 }
2815 #else
2816 77832 fd2 = dup(fd);
2817 #endif
2818
2819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77832 times.
77832 if (fd2 < 0) {
2820 char errbuf[MYSYS_STRERROR_SIZE];
2821
2822 DBUG_PRINT("error", ("Got error %d on dup", fd2));
2823
2824 set_my_errno(errno);
2825
2826 my_error(EE_OUT_OF_FILERESOURCES, MYF(0), "ib*", my_errno(),
2827 my_strerror(errbuf, sizeof(errbuf), my_errno()));
2828 }
2829
2830 77832 my_close(fd, MYF(MY_WME));
2831 }
2832
2833 77832 return fd2;
2834 }
2835
2836 /** Wrapper around MySQL's copy_and_convert function.
2837 @return number of bytes copied to 'to' */
2838 272 static ulint innobase_convert_string(
2839 void *to, /*!< out: converted string */
2840 ulint to_length, /*!< in: number of bytes reserved
2841 for the converted string */
2842 CHARSET_INFO *to_cs, /*!< in: character set to convert to */
2843 const void *from, /*!< in: string to convert */
2844 ulint from_length, /*!< in: number of bytes to convert */
2845 CHARSET_INFO *from_cs, /*!< in: character set to convert
2846 from */
2847 uint *errors) /*!< out: number of errors encountered
2848 during the conversion */
2849 {
2850 272 return (copy_and_convert((char *)to, (uint32)to_length, to_cs,
2851 (const char *)from, (uint32)from_length, from_cs,
2852 272 errors));
2853 }
2854
2855 /** Formats the raw data in "data" (in InnoDB on-disk format) that is of
2856 type DATA_(CHAR|VARCHAR|MYSQL|VARMYSQL) using "charset_coll" and writes
2857 the result to "buf". The result is converted to "system_charset_info".
2858 Not more than "buf_size" bytes are written to "buf".
2859 The result is always NUL-terminated (provided buf_size > 0) and the
2860 number of bytes that were written to "buf" is returned (including the
2861 terminating NUL).
2862 @return number of bytes that were written */
2863 272 ulint innobase_raw_format(const char *data, /*!< in: raw data */
2864 ulint data_len, /*!< in: raw data length
2865 in bytes */
2866 ulint charset_coll, /*!< in: charset collation */
2867 char *buf, /*!< out: output buffer */
2868 ulint buf_size) /*!< in: output buffer size
2869 in bytes */
2870 {
2871 /* XXX we use a hard limit instead of allocating
2872 but_size bytes from the heap */
2873 CHARSET_INFO *data_cs;
2874 char buf_tmp[8192];
2875 ulint buf_tmp_used;
2876 uint num_errors;
2877
2878 272 data_cs = all_charsets[charset_coll];
2879
2880 buf_tmp_used =
2881
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 innobase_convert_string(buf_tmp, sizeof(buf_tmp), system_charset_info,
2882 data, data_len, data_cs, &num_errors);
2883
2884 544 return (ut_str_sql_format(buf_tmp, buf_tmp_used, buf, buf_size));
2885 }
2886
2887 #endif /* !UNIV_HOTBACKUP */
2888
2889 /** Check if the string is "empty" or "none".
2890 @param[in] algorithm Compression algorithm to check
2891 @return true if no algorithm requested */
2892 233102 bool Compression::is_none(const char *algorithm) {
2893 /* NULL is the same as NONE */
2894
5/6
✓ Branch 0 taken 2338 times.
✓ Branch 1 taken 230764 times.
✓ Branch 2 taken 2338 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231750 times.
✓ Branch 5 taken 1352 times.
235440 if (algorithm == nullptr || *algorithm == 0 ||
2895
2/2
✓ Branch 0 taken 986 times.
✓ Branch 1 taken 1352 times.
2338 innobase_strcasecmp(algorithm, "none") == 0) {
2896 231750 return (true);
2897 }
2898
2899 1352 return (false);
2900 }
2901
2902 /** Check wether the compression algorithm is supported.
2903 @param[in] algorithm Compression algorithm to check
2904 @param[out] compression The type that algorithm maps to
2905 @return DB_SUCCESS or error code */
2906 232489 dberr_t Compression::check(const char *algorithm, Compression *compression) {
2907
2/2
✓ Branch 0 taken 231142 times.
✓ Branch 1 taken 1347 times.
232489 if (is_none(algorithm)) {
2908 231142 compression->m_type = NONE;
2909
2910
2/2
✓ Branch 0 taken 584 times.
✓ Branch 1 taken 763 times.
1347 } else if (innobase_strcasecmp(algorithm, "zlib") == 0) {
2911 584 compression->m_type = ZLIB;
2912
2913
2/2
✓ Branch 0 taken 755 times.
✓ Branch 1 taken 8 times.
763 } else if (innobase_strcasecmp(algorithm, "lz4") == 0) {
2914 755 compression->m_type = LZ4;
2915
2916 } else {
2917 8 return (DB_UNSUPPORTED);
2918 }
2919
2920 232481 return (DB_SUCCESS);
2921 }
2922
2923 /** Validate the algorithm string.
2924 @param[in] algorithm Compression algorithm to check
2925 @return DB_SUCCESS or error code */
2926 231092 dberr_t Compression::validate(const char *algorithm) {
2927 231092 Compression compression;
2928
2929
1/2
✓ Branch 0 taken 231092 times.
✗ Branch 1 not taken.
462184 return (check(algorithm, &compression));
2930 }
2931
2932 688 bool Compression::validate(const Compression::Type type) {
2933 688 bool ret = true;
2934
2935
1/2
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
688 switch (type) {
2936 688 case NONE:
2937 case ZLIB:
2938 case LZ4:
2939 688 break;
2940 default:
2941 ret = false;
2942 break;
2943 }
2944
2945 688 return ret;
2946 }
2947
2948 #ifndef UNIV_HOTBACKUP
2949 1980475 bool Encryption::is_empty(const char *algorithm) noexcept {
2950 /* nullptr is the same as empty */
2951 1980475 return algorithm == nullptr;
2952 }
2953
2954 1980474 bool Encryption::is_none(const char *algorithm) noexcept {
2955
2/2
✓ Branch 0 taken 1627127 times.
✓ Branch 1 taken 353347 times.
3607603 return Encryption::is_empty(algorithm) ||
2956
2/2
✓ Branch 0 taken 1589455 times.
✓ Branch 1 taken 37674 times.
3607603 innobase_strcasecmp(algorithm, "n") == 0;
2957 }
2958
2959 /** Check if the string is "y" or "Y".
2960 @param[in] algorithm Encryption algorithm to check
2961 @return true if no algorithm requested */
2962 1703030 bool Encryption::is_master_key_encryption(const char *algorithm) noexcept {
2963 1703030 return innobase_strcasecmp(algorithm, "y") == 0;
2964 }
2965
2966 /** Check if the NO algorithm was explicitly specified.
2967 @param[in] algorithm Encryption algorithm to check
2968 @return true if no algorithm explicitly requested */
2969 1568270 bool Encryption::none_explicitly_specified(bool explicit_encryption,
2970 const char *algorithm) noexcept {
2971
2/2
✓ Branch 0 taken 255776 times.
✓ Branch 1 taken 1312494 times.
1568270 if (explicit_encryption) {
2972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255776 times.
255776 ut_ad(algorithm != nullptr);
2973 255776 return innobase_strcasecmp(algorithm, "n") == 0;
2974 }
2975 1312494 return false;
2976 }
2977
2978 1721977 bool Encryption::is_keyring(const char *algoritm) noexcept {
2979
4/4
✓ Branch 0 taken 559786 times.
✓ Branch 1 taken 1162191 times.
✓ Branch 2 taken 307 times.
✓ Branch 3 taken 559479 times.
1721977 return (algoritm != nullptr && innobase_strcasecmp(algoritm, "keyring") == 0);
2980 }
2981
2982 1051659 bool Encryption::is_online_encryption_on() noexcept {
2983 1051659 return srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING;
2984 }
2985
2986 // This for now excludes MK encryption ...
2987 707034 bool Encryption::should_be_keyring_encrypted(bool explicit_encryption,
2988 const char *algorithm) noexcept {
2989
4/4
✓ Branch 0 taken 645623 times.
✓ Branch 1 taken 61412 times.
✓ Branch 2 taken 645470 times.
✓ Branch 3 taken 153 times.
1998127 return !none_explicitly_specified(explicit_encryption, algorithm) &&
2990 645623 (is_keyring(algorithm) ||
2991
4/4
✓ Branch 0 taken 635113 times.
✓ Branch 1 taken 10357 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 635102 times.
1280583 (!Encryption::is_master_key_encryption(algorithm) &&
2992 1342148 is_online_encryption_on()));
2993 }
2994
2995 341750 dberr_t Encryption::set_algorithm(const char *option,
2996 Encryption *encryption) noexcept {
2997
2/2
✓ Branch 0 taken 320993 times.
✓ Branch 1 taken 20758 times.
341750 if (is_none(option)) {
2998 320993 encryption->m_type = NONE;
2999
3000
2/2
✓ Branch 0 taken 20339 times.
✓ Branch 1 taken 420 times.
20758 } else if (innobase_strcasecmp(option, "y") == 0) {
3001 20339 encryption->m_type = AES;
3002
3003
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 112 times.
420 } else if (innobase_strcasecmp(option, "KEYRING") == 0) {
3004 308 encryption->m_type = KEYRING;
3005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 } else if (innobase_strcasecmp(option, "ONLINE_TO_KEYRING") == 0) {
3006 encryption->m_type = KEYRING;
3007 } else {
3008 112 return (DB_UNSUPPORTED);
3009 }
3010
3011 341640 return (DB_SUCCESS);
3012 }
3013
3014 340359 dberr_t Encryption::validate(const char *option) noexcept {
3015 340359 Encryption encryption;
3016
3017 340359 return (encryption.set_algorithm(option, &encryption));
3018 340361 }
3019
3020 /** Check for supported ENCRYPT := (Y | N) supported values
3021 @param[in] option Encryption option
3022 @return DB_SUCCESS or DB_UNSUPPORTED */
3023 1391 dberr_t Encryption::validate_for_tablespace(const char *option) noexcept {
3024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1391 times.
1391 if (innobase_strcasecmp(option, "KEYRING") == 0) {
3025 return DB_UNSUPPORTED;
3026 }
3027
3028 1391 Encryption encryption;
3029
3030 1391 return (encryption.set_algorithm(option, &encryption));
3031 1391 }
3032 /** Compute the next autoinc value.
3033
3034 For MySQL replication the autoincrement values can be partitioned among
3035 the nodes. The offset is the start or origin of the autoincrement value
3036 for a particular node. For n nodes the increment will be n and the offset
3037 will be in the interval [1, n]. The formula tries to allocate the next
3038 value for a particular node.
3039
3040 Note: This function is also called with increment set to the number of
3041 values we want to reserve for multi-value inserts e.g.,
3042
3043 INSERT INTO T VALUES(), (), ();
3044
3045 innobase_next_autoinc() will be called with increment set to 3 where
3046 autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for
3047 the multi-value INSERT above.
3048 @return the next value */
3049 9566310 ulonglong innobase_next_autoinc(
3050 ulonglong current, /*!< in: Current value */
3051 ulonglong need, /*!< in: count of values needed */
3052 ulonglong step, /*!< in: AUTOINC increment step */
3053 ulonglong offset, /*!< in: AUTOINC offset */
3054 ulonglong max_value) /*!< in: max value for type */
3055 {
3056 ulonglong next_value;
3057 9566310 ulonglong block = need * step;
3058
3059 /* Should never be 0. */
3060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566345 times.
9566310 ut_a(need > 0);
3061
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566383 times.
9566345 ut_a(block > 0);
3062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566425 times.
9566383 ut_a(max_value > 0);
3063
3064 /* According to MySQL documentation, if the offset is greater than
3065 the step then the offset is ignored. */
3066
2/2
✓ Branch 0 taken 16752 times.
✓ Branch 1 taken 9549673 times.
9566425 if (offset > block) {
3067 16752 offset = 0;
3068 }
3069
3070 /* Check for overflow. Current can be > max_value if the value is
3071 in reality a negative value.The visual studio compilers converts
3072 large double values automatically into unsigned long long datatype
3073 maximum value */
3074
3075
6/6
✓ Branch 0 taken 9566411 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 9566406 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 9566314 times.
✓ Branch 5 taken 92 times.
9566425 if (block >= max_value || offset > max_value || current >= max_value ||
3076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566337 times.
9566314 max_value - offset <= offset) {
3077 88 next_value = max_value;
3078 } else {
3079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566339 times.
9566337 ut_a(max_value > current);
3080
3081 9566339 ulonglong free = max_value - current;
3082
3083
4/4
✓ Branch 0 taken 9566327 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 9566322 times.
9566339 if (free < offset || free - offset <= block) {
3084 17 next_value = max_value;
3085 } else {
3086 9566322 next_value = 0;
3087 }
3088 }
3089
3090
2/2
✓ Branch 0 taken 9566327 times.
✓ Branch 1 taken 100 times.
9566427 if (next_value == 0) {
3091 ulonglong next;
3092
3093
2/2
✓ Branch 0 taken 9518601 times.
✓ Branch 1 taken 47726 times.
9566327 if (current > offset) {
3094 9518601 next = (current - offset) / step;
3095 } else {
3096 47726 next = (offset - current) / step;
3097 }
3098
3099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566331 times.
9566327 ut_a(max_value > next);
3100 9566331 next_value = next * step;
3101 /* Check for multiplication overflow. */
3102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566341 times.
9566331 ut_a(next_value >= next);
3103
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9566338 times.
9566341 ut_a(max_value > next_value);
3104
3105 /* Check for overflow */
3106
1/2
✓ Branch 0 taken 9566338 times.
✗ Branch 1 not taken.
9566338 if (max_value - next_value >= block) {
3107 9566338 next_value += block;
3108
3109
1/2
✓ Branch 0 taken 9566341 times.
✗ Branch 1 not taken.
9566338 if (max_value - next_value >= offset) {
3110 9566341 next_value += offset;
3111 } else {
3112 next_value = max_value;
3113 }
3114 } else {
3115 next_value = max_value;
3116 }
3117 }
3118
3119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566457 times.
9566438 ut_a(next_value != 0);
3120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9566459 times.
9566457 ut_a(next_value <= max_value);
3121
3122 9566459 return (next_value);
3123 }
3124
3125 /**
3126 Check whether given connection should log stats for slow query log InnoDB
3127 extensions.
3128
3129 @param[in] thd connection handle
3130 @return whether stats for slow query log InnoDB extensions should be logged
3131 */
3132 2520177506 static bool innobase_slow_log_verbose(THD *thd) noexcept {
3133
4/4
✓ Branch 0 taken 2112485553 times.
✓ Branch 1 taken 387661309 times.
✓ Branch 2 taken 150338 times.
✓ Branch 3 taken 2112357540 times.
4612658009 return thd && thd_opt_slow_log() &&
3134
2/2
✓ Branch 0 taken 2500150131 times.
✓ Branch 1 taken 20027375 times.
7132832246 unlikely(thd_log_slow_verbosity(thd) & (1ULL << SLOG_V_INNODB)) &&
3135
2/2
✓ Branch 0 taken 144140 times.
✓ Branch 1 taken 6198 times.
2520346900 !thd_is_background_thread(thd);
3136 }
3137
3138 /** Initializes some fields in an InnoDB transaction object. */
3139 1403472171 static void innobase_trx_init(
3140 THD *thd, /*!< in: user thread handle */
3141 trx_t *trx) /*!< in/out: InnoDB transaction handle */
3142 {
3143
1/2
✓ Branch 0 taken 1403478385 times.
✗ Branch 1 not taken.
1403472171 DBUG_TRACE;
3144
2/4
✓ Branch 0 taken 1403478517 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1403478517 times.
1403478385 assert(EQ_CURRENT_THD(thd));
3145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1403478517 times.
1403478517 assert(thd == trx->mysql_thd);
3146
3147
1/2
✓ Branch 0 taken 1403478351 times.
✗ Branch 1 not taken.
1403478517 trx->check_foreigns = !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS);
3148
3149 1403477908 trx->check_unique_secondary =
3150
1/2
✓ Branch 0 taken 1403477908 times.
✗ Branch 1 not taken.
1403478351 !thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS);
3151
3152 1403477908 trx->stats.set(innobase_slow_log_verbose(thd));
3153 1403475038 }
3154
3155 /** Allocates an InnoDB transaction for a MySQL handler object for DML.
3156 @return InnoDB transaction handle */
3157 16680054 trx_t *innobase_trx_allocate(THD *thd) /*!< in: user thread handle */
3158 {
3159 trx_t *trx;
3160
3161
1/2
✓ Branch 0 taken 16680148 times.
✗ Branch 1 not taken.
16680054 DBUG_TRACE;
3162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16680148 times.
16680148 assert(thd != nullptr);
3163
2/4
✓ Branch 0 taken 16680147 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16680147 times.
16680148 assert(EQ_CURRENT_THD(thd));
3164
3165 16680147 MONITOR_ATOMIC_INC(MONITOR_TRX_ALLOCATIONS);
3166
1/2
✓ Branch 0 taken 16680158 times.
✗ Branch 1 not taken.
16680086 trx = trx_allocate_for_mysql();
3167
3168
1/2
✓ Branch 0 taken 16680157 times.
✗ Branch 1 not taken.
16680158 rw_lock_s_lock(&purge_sys->latch, UT_LOCATION_HERE);
3169
3170
3/4
✓ Branch 0 taken 16680157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7881 times.
✓ Branch 3 taken 16672277 times.
16680157 if (purge_sys->thds.find(thd) != purge_sys->thds.end()) {
3171 7881 trx->purge_sys_trx = true;
3172 }
3173
3174
1/2
✓ Branch 0 taken 16680156 times.
✗ Branch 1 not taken.
16680158 rw_lock_s_unlock(&purge_sys->latch);
3175
3176 16680156 trx->mysql_thd = thd;
3177
3178
1/2
✓ Branch 0 taken 16680158 times.
✗ Branch 1 not taken.
16680156 innobase_trx_init(thd, trx);
3179
3180 16680158 return trx;
3181 16680158 }
3182
3183 /** Gets the InnoDB transaction handle for a MySQL handler object, creates
3184 an InnoDB transaction struct if the corresponding MySQL thread struct still
3185 lacks one.
3186 @return InnoDB transaction handle */
3187 1403472558 trx_t *check_trx_exists(THD *thd) /*!< in: user thread handle */
3188 {
3189 /* We request to stop master thread in srv_shutdown, which is invoked
3190 after DD has been shut down. Since that point of time, we must not need
3191 transaction objects for any reasons. */
3192
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1403472743 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1403471554 times.
2806945301 ut_ad(srv_shutdown_state_matches([](auto state) {
3193 return state < SRV_SHUTDOWN_MASTER_STOP ||
3194 state == SRV_SHUTDOWN_EXIT_THREADS;
3195 }));
3196
3197 1403471554 trx_t *&trx = thd_to_trx(thd);
3198
3199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1403472636 times.
1403472524 ut_ad(EQ_CURRENT_THD(thd));
3200
3201
2/2
✓ Branch 0 taken 16679775 times.
✓ Branch 1 taken 1386792861 times.
1403472636 if (trx == nullptr) {
3202 16679775 trx = innobase_trx_allocate(thd);
3203
3204 /* User trx can be forced to rollback,
3205 so we unset the disable flag. */
3206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16679798 times.
16679794 ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE);
3207 16679798 trx->in_innodb &= TRX_FORCE_ROLLBACK_MASK;
3208 } else {
3209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1386792504 times.
1386792861 ut_a(trx->magic_n == TRX_MAGIC_N);
3210
3211 1386792504 innobase_trx_init(thd, trx);
3212 }
3213
3214 1403478007 return (trx);
3215 }
3216
3217 /** Get the transaction of the current connection handle, if either exists.
3218 @return transaction of the current connection handle, or NULL. */
3219 trx_t *innobase_get_trx(void) {
3220 THD *const thd = current_thd;
3221 if (UNIV_UNLIKELY(!thd)) return (nullptr);
3222
3223 return (thd_to_trx(thd));
3224 }
3225
3226 /** Get the transaction of the current connection handle if slow query log
3227 InnoDB extended statistics should be collected.
3228 @return transaction object if statistics should be collected, or NULL. */
3229 1116718551 trx_t *innobase_get_trx_for_slow_log(void) noexcept {
3230 1116718551 THD *thd = current_thd;
3231
2/2
✓ Branch 0 taken 1116693461 times.
✓ Branch 1 taken 43598 times.
1116734900 if (UNIV_LIKELY(!innobase_slow_log_verbose(thd))) return (nullptr);
3232 43598 trx_t *trx = thd_to_trx(thd);
3233
6/6
✓ Branch 0 taken 41755 times.
✓ Branch 1 taken 1843 times.
✓ Branch 2 taken 41557 times.
✓ Branch 3 taken 198 times.
✓ Branch 4 taken 41557 times.
✓ Branch 5 taken 2041 times.
43598 if (trx && UNIV_UNLIKELY(trx->stats.enabled())) return (trx);
3234 2041 return (nullptr);
3235 }
3236
3237 /** InnoDB transaction object that is currently associated with THD is
3238 replaced with that of the 2nd argument. The previous value is
3239 returned through the 3rd argument's buffer, unless it's NULL. When
3240 the buffer is not provided (value NULL) that should mean the caller
3241 restores previously saved association so the current trx has to be
3242 additionally freed from all association with MYSQL.
3243
3244 @param[in,out] thd MySQL thread handle
3245 @param[in] new_trx_arg replacement trx_t
3246 @param[in,out] ptr_trx_arg pointer to a buffer to store old trx_t */
3247 1301 static void innodb_replace_trx_in_thd(THD *thd, void *new_trx_arg,
3248 void **ptr_trx_arg) {
3249
1/2
✓ Branch 0 taken 1301 times.
✗ Branch 1 not taken.
1301 DBUG_TRACE;
3250
1/2
✓ Branch 0 taken 1301 times.
✗ Branch 1 not taken.
1301 trx_t *&trx = thd_to_trx(thd);
3251
3252
5/8
✓ Branch 0 taken 346 times.
✓ Branch 1 taken 955 times.
✓ Branch 2 taken 346 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 346 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1301 times.
1301 ut_ad(new_trx_arg == nullptr || (((trx_t *)new_trx_arg)->mysql_thd == thd &&
3253 !((trx_t *)new_trx_arg)->is_recovered));
3254
3255
2/2
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 948 times.
1301 if (ptr_trx_arg) {
3256 353 *ptr_trx_arg = trx;
3257
3258
5/8
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 347 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 347 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 353 times.
353 ut_ad(trx == nullptr || (trx->mysql_thd == thd && !trx->is_recovered));
3259
3260
2/2
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 280 times.
948 } else if (trx != nullptr) {
3261
2/4
✓ Branch 0 taken 668 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 668 times.
668 ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx));
3262
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 596 times.
668 if (trx->state.load(std::memory_order_relaxed) == TRX_STATE_NOT_STARTED) {
3263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 ut_ad(thd == trx->mysql_thd);
3264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 ut_ad(!trx_is_registered_for_2pc(trx));
3265
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 trx_free_for_mysql(trx);
3266 } else {
3267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 596 times.
596 ut_ad(thd == trx->mysql_thd);
3268
2/4
✓ Branch 0 taken 596 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 596 times.
596 ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED));
3269 /* The choice not to disconnect transaction when
3270 trx_is_redo_rseg_updated(trx) is false is copied from
3271 the existing detach logic for prepared XA
3272 transactions in innobase_close_connection().
3273 If transaction did not modify anything, rolling it back doesn't modify
3274 the db, but lets us deregister and free the trx object to conserve
3275 resources, while still allowing XA COMMIT it in the future, as it
3276 succeeds on missing xids. */
3277
2/2
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 8 times.
596 if (trx_is_redo_rseg_updated(trx)) {
3278
1/2
✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
588 trx_disconnect_prepared(trx);
3279 } else {
3280
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 trx_rollback_for_mysql(trx);
3281 8 trx_deregister_from_2pc(trx);
3282
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 trx_free_for_mysql(trx);
3283 }
3284 }
3285 }
3286 1301 trx = static_cast<trx_t *>(new_trx_arg);
3287 1301 }
3288
3289 /** Note that a transaction has been registered with MySQL 2PC coordinator. */
3290 115463619 static inline void trx_register_for_2pc(trx_t *trx) /* in: transaction */
3291 {
3292 115463619 trx->is_registered = true;
3293 115463619 }
3294
3295 22257907 static inline void trx_deregister_from_2pc(trx_t *trx) {
3296 22257907 trx->is_registered = false;
3297 22257907 }
3298
3299 /** Copy table flags from MySQL's HA_CREATE_INFO into an InnoDB table object.
3300 Those flags are stored in .frm file and end up in the MySQL table object,
3301 but are frequently used inside InnoDB so we keep their copies into the
3302 InnoDB table object. */
3303 429267 static void innobase_copy_frm_flags_from_create_info(
3304 dict_table_t *innodb_table, /*!< in/out: InnoDB table */
3305 const HA_CREATE_INFO *create_info) /*!< in: create info */
3306 {
3307 bool ps_on;
3308 bool ps_off;
3309
3310
2/2
✓ Branch 0 taken 228805 times.
✓ Branch 1 taken 200463 times.
429267 if (innodb_table->is_temporary()) {
3311 /* Temp tables do not use persistent stats. */
3312 228805 ps_on = false;
3313 228805 ps_off = true;
3314 } else {
3315 200463 ps_on = create_info->table_options & HA_OPTION_STATS_PERSISTENT;
3316 200463 ps_off = create_info->table_options & HA_OPTION_NO_STATS_PERSISTENT;
3317 }
3318
3319 429268 dict_stats_set_persistent(innodb_table, ps_on, ps_off);
3320
3321 429266 dict_stats_auto_recalc_set(
3322 429266 innodb_table, create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
3323 429266 create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
3324
3325 429267 innodb_table->stats_sample_pages = create_info->stats_sample_pages;
3326 429267 }
3327
3328 /** Copy table flags from MySQL's TABLE_SHARE into an InnoDB table object.
3329 Those flags are stored in .frm file and end up in the MySQL table object,
3330 but are frequently used inside InnoDB so we keep their copies into the
3331 InnoDB table object. */
3332 4649373 void innobase_copy_frm_flags_from_table_share(
3333 dict_table_t *innodb_table, /*!< in/out: InnoDB table */
3334 const TABLE_SHARE *table_share) /*!< in: table share */
3335 {
3336 bool ps_on;
3337 bool ps_off;
3338
3339
2/2
✓ Branch 0 taken 349111 times.
✓ Branch 1 taken 4300262 times.
4649373 if (innodb_table->is_temporary()) {
3340 /* Temp tables do not use persistent stats */
3341 349111 ps_on = false;
3342 349111 ps_off = true;
3343 } else {
3344 4300262 ps_on = table_share->db_create_options & HA_OPTION_STATS_PERSISTENT;
3345 4300262 ps_off = table_share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT;
3346 }
3347
3348 4649373 dict_stats_set_persistent(innodb_table, ps_on, ps_off);
3349
3350 4649373 dict_stats_auto_recalc_set(
3351 4649373 innodb_table, table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON,
3352 4649373 table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF);
3353
3354 4649373 innodb_table->stats_sample_pages = table_share->stats_sample_pages;
3355 4649373 }
3356
3357 408627 int ha_innobase::srv_concurrency_enter() {
3358 408627 auto err = innobase_srv_conc_enter_innodb(m_prebuilt);
3359
3360 408627 trx_t *trx = m_prebuilt->trx;
3361 408627 return convert_error_code_to_mysql(err, 0, trx->mysql_thd);
3362 }
3363
3364 408627 void ha_innobase::srv_concurrency_exit() {
3365 408627 innobase_srv_conc_exit_innodb(m_prebuilt);
3366 408627 }
3367
3368 /** Construct ha_innobase handler. */
3369
3370 10196990 ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg)
3371 : handler(hton, table_arg),
3372 10197007 m_ds_mrr(this),
3373 10197005 m_prebuilt(),
3374 10197005 m_user_thd(),
3375 10197005 m_int_table_flags(
3376 HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_CAN_SQL_HANDLER |
3377 HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_PRIMARY_KEY_IN_READ_INDEX |
3378 HA_BINLOG_ROW_CAPABLE | HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
3379 HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT | HA_CAN_FULLTEXT_EXT |
3380 HA_CAN_FULLTEXT_HINTS | HA_CAN_EXPORT | HA_CAN_RTREEKEYS |
3381 HA_NO_READ_LOCAL_LOCK | HA_GENERATED_COLUMNS |
3382 HA_ATTACHABLE_TRX_COMPATIBLE | HA_CAN_INDEX_VIRTUAL_GENERATED_COLUMN |
3383 HA_DESCENDING_INDEX | HA_MULTI_VALUED_KEY_SUPPORT |
3384 HA_BLOB_PARTIAL_UPDATE | HA_SUPPORTS_GEOGRAPHIC_GEOMETRY_COLUMN |
3385 HA_SUPPORTS_DEFAULT_EXPRESSION | HA_ONLINE_ANALYZE),
3386 10197005 m_start_of_scan(),
3387 10197005 m_stored_select_lock_type(LOCK_NONE_UNSET),
3388 10196990 m_mysql_has_locked() {}
3389
3390 /** Updates the user_thd field in a handle and also allocates a new InnoDB
3391 transaction handle if needed, and updates the transaction fields in the
3392 m_prebuilt struct. */
3393 1248722931 void ha_innobase::update_thd(THD *thd) /*!< in: thd to use the handle */
3394 {
3395
1/2
✓ Branch 0 taken 1248729219 times.
✗ Branch 1 not taken.
1248722931 DBUG_TRACE;
3396
5/8
✓ Branch 0 taken 1248728294 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1248726656 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66467 times.
✓ Branch 5 taken 1248660189 times.
✓ Branch 6 taken 66467 times.
✗ Branch 7 not taken.
1248729219 DBUG_PRINT("ha_innobase::update_thd",
3397 ("user_thd: %p -> %p", m_user_thd, thd));
3398
3399 /* The table should have been opened in ha_innobase::open(). */
3400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1248725779 times.
1248726656 assert(m_prebuilt->table->n_ref_count > 0);
3401
3402
1/2
✓ Branch 0 taken 1248728890 times.
✗ Branch 1 not taken.
1248725779 trx_t *trx = check_trx_exists(thd);
3403
3404
1/2
✓ Branch 0 taken 1248725007 times.
✗ Branch 1 not taken.
1248728890 TrxInInnoDB trx_in_innodb(trx);
3405
3406
2/2
✓ Branch 0 taken 24397928 times.
✓ Branch 1 taken 1224327079 times.
1248725007 if (m_prebuilt->trx != trx) {
3407
1/2
✓ Branch 0 taken 24397802 times.
✗ Branch 1 not taken.
24397928 row_update_prebuilt_trx(m_prebuilt, trx);
3408 }
3409
3410 1248724881 m_user_thd = thd;
3411
3412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1248724881 times.
1248724881 assert(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
3413
2/4
✓ Branch 0 taken 1248725418 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1248725418 times.
1248724881 assert(m_prebuilt->trx == thd_to_trx(m_user_thd));
3414 1248725418 }
3415
3416 /** Updates the user_thd field in a handle and also allocates a new InnoDB
3417 transaction handle if needed, and updates the transaction fields in the
3418 m_prebuilt struct. */
3419
3420 1004191520 void ha_innobase::update_thd() {
3421 1004191520 THD *thd = ha_thd();
3422
3423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1004190847 times.
1004192379 ut_ad(EQ_CURRENT_THD(thd));
3424 1004190847 update_thd(thd);
3425 1004193831 }
3426
3427 /** Registers an InnoDB transaction with the MySQL 2PC coordinator, so that
3428 the MySQL XA code knows to call the InnoDB prepare and commit, or rollback
3429 for the transaction. This MUST be called for every transaction for which
3430 the user may call commit or rollback. Calling this several times to register
3431 the same transaction is allowed, too. This function also registers the
3432 current SQL statement. */
3433 115463523 void innobase_register_trx(handlerton *hton, /* in: Innobase handlerton */
3434 THD *thd, /* in: MySQL thd (connection) object */
3435 trx_t *trx) /* in: transaction to register */
3436 {
3437
1/2
✓ Branch 0 taken 115463918 times.
✗ Branch 1 not taken.
115463523 const ulonglong trx_id = static_cast<ulonglong>(trx_get_id_for_print(trx));
3438
3439
1/2
✓ Branch 0 taken 115464537 times.
✗ Branch 1 not taken.
115463918 trans_register_ha(thd, false, hton, &trx_id);
3440
3441
4/4
✓ Branch 0 taken 21634220 times.
✓ Branch 1 taken 93829364 times.
✓ Branch 2 taken 1114947 times.
✓ Branch 3 taken 114349058 times.
137099178 if (!trx_is_registered_for_2pc(trx) &&
3442
3/4
✓ Branch 0 taken 21634641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1114925 times.
✓ Branch 3 taken 20519716 times.
21634220 thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
3443
1/2
✓ Branch 0 taken 1115058 times.
✗ Branch 1 not taken.
1114947 trans_register_ha(thd, true, hton, &trx_id);
3444 }
3445
3446 115464116 trx_register_for_2pc(trx);
3447 115463867 }
3448
3449 /** Quote a standard SQL identifier like tablespace, index or column name.
3450 @param[in] file output stream
3451 @param[in] trx InnoDB transaction, or NULL
3452 @param[in] id identifier to quote */
3453 1038 void innobase_quote_identifier(FILE *file, trx_t *trx, const char *id) {
3454 const int q =
3455
1/2
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
1038 trx != nullptr && trx->mysql_thd != nullptr
3456
1/2
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
2076 ? get_quote_char_for_identifier(trx->mysql_thd, id, strlen(id))
3457 1038 : '`';
3458
3459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1038 times.
1038 if (q == EOF) {
3460 fputs(id, file);
3461 } else {
3462 1038 putc(q, file);
3463
3464
2/2
✓ Branch 0 taken 4518 times.
✓ Branch 1 taken 1038 times.
5556 while (int c = *id++) {
3465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4518 times.
4518 if (c == q) {
3466 putc(c, file);
3467 }
3468 4518 putc(c, file);
3469 4518 }
3470
3471 1038 putc(q, file);
3472 }
3473 1038 }
3474
3475 /** Convert a table name to the MySQL system_charset_info (UTF-8)
3476 and quote it.
3477 @param[out] buf buffer for converted identifier
3478 @param[in] buflen length of buf, in bytes
3479 @param[in] id identifier to convert
3480 @param[in] idlen length of id, in bytes
3481 @param[in] thd MySQL connection thread, or NULL
3482 @return pointer to the end of buf */
3483 31144 static char *innobase_convert_identifier(char *buf, ulint buflen,
3484 const char *id, ulint idlen,
3485 THD *thd) {
3486 31144 const char *s = id;
3487
3488 char nz[MAX_TABLE_NAME_LEN + 1];
3489 char nz2[MAX_TABLE_NAME_LEN + 1];
3490
3491 /* Decode the table name. The MySQL function expects
3492 a NUL-terminated string. The input and output strings
3493 buffers must not be shared. */
3494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31144 times.
31144 ut_a(idlen <= MAX_TABLE_NAME_LEN);
3495 31144 memcpy(nz, id, idlen);
3496 31144 nz[idlen] = 0;
3497
3498 31144 s = nz2;
3499 idlen =
3500
1/2
✓ Branch 0 taken 31144 times.
✗ Branch 1 not taken.
31144 explain_filename(thd, nz, nz2, sizeof nz2, EXPLAIN_PARTITIONS_AS_COMMENT);
3501
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 31138 times.
31144 if (idlen > buflen) {
3502 6 idlen = buflen;
3503 }
3504 31144 memcpy(buf, s, idlen);
3505 31144 return (buf + idlen);
3506 }
3507
3508 /** Convert a table name to the MySQL system_charset_info (UTF-8).
3509 @return pointer to the end of buf */
3510 15809 char *innobase_convert_name(
3511 char *buf, /*!< out: buffer for converted identifier */
3512 ulint buflen, /*!< in: length of buf, in bytes */
3513 const char *id, /*!< in: table name to convert */
3514 ulint idlen, /*!< in: length of id, in bytes */
3515 THD *thd) /*!< in: MySQL connection thread, or NULL */
3516 {
3517 15809 char *s = buf;
3518 15809 const char *bufend = buf + buflen;
3519
3520 15809 const char *slash = (const char *)memchr(id, '/', idlen);
3521
3522
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 15341 times.
15809 if (slash == nullptr) {
3523 468 return (innobase_convert_identifier(buf, buflen, id, idlen, thd));
3524 }
3525
3526 /* Print the database name and table name separately. */
3527 15341 s = innobase_convert_identifier(s, bufend - s, id, slash - id, thd);
3528
2/2
✓ Branch 0 taken 15335 times.
✓ Branch 1 taken 6 times.
15341 if (s < bufend) {
3529 15335 *s++ = '.';
3530 15335 s = innobase_convert_identifier(s, bufend - s, slash + 1,
3531 15335 idlen - (slash - id) - 1, thd);
3532 }
3533
3534 15341 return (s);
3535 }
3536
3537 /** A wrapper function of innobase_convert_name(), convert a table name
3538 to the MySQL system_charset_info (UTF-8) and quote it if needed.
3539 @param[out] buf Buffer for converted identifier
3540 @param[in] buflen Length of buf, in bytes
3541 @param[in] name Table name to format */
3542 181 void innobase_format_name(char *buf, ulint buflen, const char *name) {
3543 const char *bufend;
3544
3545 181 bufend = innobase_convert_name(buf, buflen, name, strlen(name), nullptr);
3546
3547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 ut_ad((ulint)(bufend - buf) < buflen);
3548
3549 181 buf[bufend - buf] = '\0';
3550 181 }
3551
3552 /** Determines if the currently running transaction has been interrupted.
3553 @return true if interrupted */
3554 411305509 bool trx_is_interrupted(const trx_t *trx) /*!< in: transaction */
3555 {
3556
6/6
✓ Branch 0 taken 411132933 times.
✓ Branch 1 taken 172576 times.
✓ Branch 2 taken 411132897 times.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 411132520 times.
411305509 return (trx && trx->mysql_thd && thd_killed(trx->mysql_thd));
3557 }
3558
3559 /** Determines if the currently running transaction is in strict mode.
3560 @return true if strict */
3561 374181 bool trx_is_strict(trx_t *trx) /*!< in: transaction */
3562 {
3563 /* Relax strict check if table is in truncate create table */
3564
4/6
✓ Branch 0 taken 374181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 374181 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 370647 times.
✓ Branch 5 taken 3534 times.
744828 return (trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode) &&
3565
2/2
✓ Branch 0 taken 303604 times.
✓ Branch 1 taken 67043 times.
744828 (!trx->in_truncate));
3566 }
3567
3568 /** Resets some fields of a m_prebuilt struct. The template is used in fast
3569 retrieval of just those column values MySQL needs in its processing. */
3570 449527008 void ha_innobase::reset_template(void) {
3571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 449528424 times.
449527008 ut_ad(m_prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
3572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 449528701 times.
449528424 ut_ad(m_prebuilt->magic_n2 == m_prebuilt->magic_n);
3573
3574 /* Force table to be freed in close_thread_table(). */
3575
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 449528742 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
449528701 DBUG_EXECUTE_IF(
3576 "free_table_in_fts_query",
3577 if (m_prebuilt->in_fts_query) { table->invalidate_dict(); });
3578
3579 449528742 m_prebuilt->keep_other_fields_on_keyread = 0;
3580 449528742 m_prebuilt->read_just_key = 0;
3581 449528742 m_prebuilt->in_fts_query = false;
3582 449528742 m_prebuilt->m_end_range = false;
3583
3584 /* Reset index condition pushdown state. */
3585
2/2
✓ Branch 0 taken 2133 times.
✓ Branch 1 taken 449526609 times.
449528742 if (m_prebuilt->idx_cond) {
3586 2133 m_prebuilt->idx_cond = false;
3587 2133 m_prebuilt->idx_cond_n_cols = 0;
3588 /* Invalidate m_prebuilt->mysql_template
3589 in ha_innobase::write_row(). */
3590 2133 m_prebuilt->template_type = ROW_MYSQL_NO_TEMPLATE;
3591 }
3592 449528742 }
3593
3594 /** Call this when you have opened a new table handle in HANDLER, before you
3595 call index_read_map() etc. Actually, we can let the cursor stay open even
3596 over a transaction commit! Then you should call this before every operation,
3597 fetch next etc. This function inits the necessary things even after a
3598 transaction commit. */
3599
3600 41600 void ha_innobase::init_table_handle_for_HANDLER(void) {
3601 /* If current thd does not yet have a trx struct, create one.
3602 If the current handle does not yet have a m_prebuilt struct, create
3603 one. Update the trx pointers in the m_prebuilt struct. Normally
3604 this operation is done in external_lock. */
3605
3606
2/4
✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41600 times.
✗ Branch 3 not taken.
41600 update_thd(ha_thd());
3607
3608 /* Initialize the m_prebuilt struct much like it would be inited in
3609 external_lock */
3610
3611
1/2
✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
41600 innobase_srv_conc_force_exit_innodb(m_prebuilt->trx);
3612
3613 /* If the transaction is not started yet, start it */
3614
3615
1/2
✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
41600 trx_start_if_not_started_xa(m_prebuilt->trx, false, UT_LOCATION_HERE);
3616
3617
1/2
✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
41600 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
3618
3619 /* Assign a read view if the transaction does not have it yet */
3620
3621
1/2
✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
41600 trx_assign_read_view(m_prebuilt->trx);
3622
3623
1/2
✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
41600 innobase_register_trx(ht, m_user_thd, m_prebuilt->trx);
3624
3625 /* We did the necessary inits in this function, no need to repeat them
3626 in row_search_for_mysql */
3627
3628 41600 m_prebuilt->sql_stat_start = false;
3629
3630 /* We let HANDLER always to do the reads as consistent reads, even
3631 if the trx isolation level would have been specified as SERIALIZABLE */
3632
3633 41600 m_prebuilt->select_lock_type = LOCK_NONE;
3634 41600 m_prebuilt->select_mode = SELECT_ORDINARY;
3635 41600 m_stored_select_lock_type = LOCK_NONE;
3636
3637 /* Always fetch all columns in the index record */
3638
3639 41600 m_prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
3640
3641 /* We want always to fetch all columns in the whole row? Or do
3642 we???? */
3643
3644 41600 m_prebuilt->used_in_HANDLER = true;
3645
3646
1/2
✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
41600 reset_template();
3647 41600 }
3648
3649 /** Free any resources that were allocated and return failure.
3650 @return always return 1 */
3651 104 static int innodb_init_abort() {
3652
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
104 DBUG_TRACE;
3653
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
104 srv_shutdown_exit_threads();
3654
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
104 innodb_space_shutdown();
3655
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
104 innobase::component_services::deinitialize_service_handles();
3656
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
104 release_plugin_services();
3657 104 return 1;
3658 104 }
3659
3660 /** Open or create InnoDB data files.
3661 @param[in] dict_init_mode whether to create or open the files
3662 @param[in,out] tablespaces predefined tablespaces created by the DDSE
3663 @return 0 on success, 1 on failure */
3664 [[nodiscard]] static int innobase_init_files(
3665 dict_init_mode_t dict_init_mode,
3666 List<const Plugin_tablespace> *tablespaces,
3667 bool &is_dd_encrypted);
3668
3669 /** Initialize InnoDB for being used to store the DD tables.
3670 Create the required files according to the dict_init_mode.
3671 Create strings representing the required DDSE tables, i.e.,
3672 tables that InnoDB expects to exist in the DD,
3673 and add them to the appropriate out parameter.
3674
3675 @param[in] dict_init_mode How to initialize files
3676
3677 @param[in] version Target DD version if a new server
3678 is being installed.
3679 0 if restarting an existing server.
3680
3681 @param[out] tables List of SQL DDL statements
3682 for creating DD tables that
3683 are needed by the DDSE.
3684
3685 @param[out] tablespaces List of meta data for predefined
3686 tablespaces created by the DDSE.
3687
3688 @retval true An error occurred.
3689 @retval false Success - no errors. */
3690 static bool innobase_ddse_dict_init(dict_init_mode_t dict_init_mode,
3691 uint version,
3692 List<const dd::Object_table> *tables,
3693 List<const Plugin_tablespace> *tablespaces);
3694
3695 /** Save the state of undo tablespaces from the dd to the undo::Tablespace
3696 @param[in] space_id tablespace ID
3697 @param[in] dd_space dd::Tablespace object
3698 @return true if success and false if the undo tablespace state is not saved. */
3699 23335 bool apply_dd_undo_state(space_id_t space_id, const dd::Tablespace *dd_space) {
3700 23335 bool success = true;
3701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23335 times.
23335 if (!fsp_is_undo_tablespace(space_id)) {
3702 return (success);
3703 }
3704
3705 /* Get the state of undo tablespaces from the DD. */
3706 23335 dd_space_states state = dd_tablespace_get_state_enum(dd_space, space_id);
3707
3708 23335 undo::spaces->s_lock();
3709
3710 23335 space_id_t space_num = undo::id2num(space_id);
3711 23335 undo::Tablespace *undo_space = undo::spaces->find(space_num);
3712
3713
3/5
✓ Branch 0 taken 23273 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
23335 switch (state) {
3714 23273 case DD_SPACE_STATE__LAST:
3715 /* If the "state" key is missing the DD might have been built with
3716 an older version. */
3717 case DD_SPACE_STATE_ACTIVE:
3718 /* Explicit undo spaces with no undo logs are set empty during
3719 startup to avoid getting undo. */
3720
2/2
✓ Branch 0 taken 225 times.
✓ Branch 1 taken 23048 times.
23273 if (undo_space->is_empty()) {
3721 225 undo_space->set_active();
3722 }
3723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23273 times.
23273 ut_ad(undo_space->is_active());
3724 23273 break;
3725 2 case DD_SPACE_STATE_INACTIVE:
3726 2 undo_space->set_inactive_explicit();
3727 2 srv_wake_purge_thread_if_not_active();
3728
3729 2 break;
3730 60 case DD_SPACE_STATE_EMPTY:
3731 60 undo_space->set_empty();
3732 60 break;
3733 case DD_SPACE_STATE_NORMAL:
3734 case DD_SPACE_STATE_DISCARDED:
3735 case DD_SPACE_STATE_CORRUPTED:
3736 success = false;
3737 break;
3738 }
3739
3740 23335 undo::spaces->s_unlock();
3741
3742 23335 return (success);
3743 }
3744
3745 /** Initialize the set of hard coded DD table ids.
3746 @param[in] dd_table_id Table id of DD table. */
3747 static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id);
3748
3749 /** Validate the DD tablespace data against what's read during the
3750 directory scan on startup. */
3751 class Validate_files {
3752 using DD_tablespaces = std::vector<const dd::Tablespace *>;
3753 using Const_iter = DD_tablespaces::const_iterator;
3754
3755 public:
3756 /** Constructor */
3757 11531 Validate_files()
3758 11531 : m_mutex(),
3759 11531 m_space_max_id(),
3760 11531 m_n_to_check(),
3761 11531 m_n_threads(),
3762 11531 m_start_time(std::chrono::steady_clock::time_point{}),
3763 11531 m_n_validated(),
3764 11531 m_n_skipped(),
3765 11531 m_n_moved(),
3766 11531 m_n_missing(),
3767 11531 m_n_deleted(),
3768 11531 m_n_errors() {}
3769
3770 /** Validate the discovered tablespaces against the DD and attempt to open
3771 any DD tablespace not already open using a Parallel For Loop (par_for).
3772 @param[in] tablespaces Tablespace files read from the DD
3773 @return DB_SUCCESS if all OK */
3774 [[nodiscard]] dberr_t validate(const DD_tablespaces &tablespaces);
3775
3776 private:
3777 /** Validate a range of tablespaces from the DD.
3778 1. Compare the discovered files against those known to the dictionary.
3779 2. Open any tablespace known to the DD but not discovered and opened
3780 from the known directories.
3781 3. Update the DD if a tablespace has moved.
3782 4. Update the DD if an undo tablespace was truncated and replaced.
3783 5. If innodb_validate_tablespace_paths is set and this is not called
3784 while in recovery, only validate undo tablespaces.
3785 6. Track the number of skipped, moved, missing and deleted tablespaces.
3786 7. Return failure for any unexpected error.
3787 @param[in] begin Start of the slice
3788 @param[in] end End of the slice
3789 @param[in] thread_id Thread ID */
3790 void check(const Const_iter &begin, const Const_iter &end, size_t thread_id);
3791
3792 /** @return true if there were failures. */
3793 23062 bool failed() const { return (m_n_errors.load() != 0); }
3794
3795 /** @return the maximum tablespace ID found. */
3796 11531 space_id_t get_space_max_id() const { return (m_space_max_id); }
3797
3798 private:
3799 /** Mutex protecting the parallel check. */
3800 std::mutex m_mutex;
3801
3802 /** Maximum tablespace ID found. */
3803 space_id_t m_space_max_id;
3804
3805 /** Number of tablespaces to check. */
3806 size_t m_n_to_check;
3807
3808 /** Number of threads used in the parallel for. */
3809 size_t m_n_threads;
3810
3811 /** The time when Validate_files::validate() starts or the last time
3812 one of the threads reported progress. */
3813 std::atomic<std::chrono::steady_clock::time_point> m_start_time;
3814 static_assert(decltype(m_start_time)::is_always_lock_free);
3815
3816 /** Number of tablespaces validated. */
3817 std::atomic_size_t m_n_validated;
3818
3819 /** Number of tablespaces skipped. */
3820 std::atomic_size_t m_n_skipped;
3821
3822 /** Number of tablespaces moved. */
3823 std::atomic_size_t m_n_moved;
3824
3825 /** Number of tablespaces missing. */
3826 std::atomic_size_t m_n_missing;
3827
3828 /** Number of tablespaces deleted. */
3829 std::atomic_size_t m_n_deleted;
3830
3831 /** Number of threads that failed. */
3832 std::atomic_size_t m_n_errors;
3833 };
3834
3835 11531 void Validate_files::check(const Const_iter &begin, const Const_iter &end,
3836 size_t thread_id) {
3837 11531 const auto sys_space_name = dict_sys_t::s_sys_space_name;
3838
3839
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 auto heap = mem_heap_create(FN_REFLEN * 2 + 1, UT_LOCATION_HERE);
3840
3841 /* If the setting for innodb_validate_tablespace_paths is NO and we are
3842 not in recovery, then only validate undo tablespaces. */
3843 11531 const bool ibd_validate =
3844
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 11517 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 11 times.
11531 srv_validate_tablespace_paths || recv_needed_recovery;
3845
3846 11531 std::string prefix;
3847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
11531 if (m_n_threads > 0) {
3848 std::ostringstream msg;
3849 msg << "Thread# " << thread_id << " - ";
3850 prefix = msg.str();
3851 }
3852
3853
2/2
✓ Branch 0 taken 127913 times.
✓ Branch 1 taken 11531 times.
139444 for (auto it = begin; it != end; ++it) {
3854 127913 const auto &dd_tablespace = *it;
3855
3856
3/6
✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127913 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 127913 times.
127913 if (std::chrono::steady_clock::now() - m_start_time.load() >=
3857 PRINT_INTERVAL) {
3858 m_start_time = std::chrono::steady_clock::now();
3859
3860 std::ostringstream msg;
3861
3862 if (m_n_threads) {
3863 msg << m_n_threads << "threads have validated ";
3864 } else {
3865 msg << "Validated ";
3866 }
3867
3868 msg << m_n_validated << " out of " << m_n_to_check
3869 << " tablespaces so far.";
3870
3871 if (m_n_skipped > 0) {
3872 msg << " Skipped=" << m_n_skipped << ".";
3873 }
3874 if (m_n_moved > 0) {
3875 msg << " Moved=" << m_n_moved << ".";
3876 }
3877 if (m_n_missing > 0) {
3878 msg << " Missing=" << m_n_missing << ".";
3879 }
3880 if (m_n_deleted > 0) {
3881 msg << " Deleted=" << m_n_deleted << ".";
3882 }
3883
3884 ib::info(ER_IB_MSG_525) << msg.str();
3885 }
3886
3887
3/6
✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127913 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 127913 times.
127913 if (dd_tablespace->engine() != innobase_hton_name) {
3888 ++m_n_skipped;
3889 61977 continue;
3890 }
3891
3892 127913 bool is_enc_in_progress{false};
3893
1/2
✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
127913 const auto &p = dd_tablespace->se_private_data();
3894
1/2
✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
127913 const auto &o = dd_tablespace->options();
3895
1/2
✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
127913 const char *space_name = dd_tablespace->name().c_str();
3896 127913 const auto se_key_value = dd_space_key_strings;
3897
3898 /* There should be exactly one file name associated
3899 with each InnoDB tablespace, except innodb_system */
3900
3901 space_id_t space_id;
3902
3/6
✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127913 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 127913 times.
127913 if (p.get(se_key_value[DD_SPACE_ID], &space_id)) {
3903 /* Failed to fetch the tablespace ID */
3904 ++m_n_errors;
3905 break;
3906 }
3907
3908 /* If --innodb_validate_tablespace_paths=OFF and
3909 startup is not in recovery, then skip all IBD files. */
3910
7/8
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 127714 times.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 177 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 177 times.
✓ Branch 7 taken 127736 times.
127913 if (!ibd_validate && !fsp_is_undo_tablespace(space_id)) {
3911 177 ++m_n_skipped;
3912 177 continue;
3913 }
3914
3915 /* Do not open a discovered tablespace that is currently discarded.
3916 It will be opened properly when it is imported. */
3917
1/2
✓ Branch 0 taken 127736 times.
✗ Branch 1 not taken.
127736 dd_space_states dd_state = dd_tablespace_get_state_enum(&p, space_id);
3918
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 127658 times.
127736 if (dd_state == DD_SPACE_STATE_DISCARDED) {
3919 78 ++m_n_skipped;
3920 78 continue;
3921 }
3922
3923
5/10
✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127658 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 127657 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 127658 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
255317 if (p.exists(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS]) &&
3924
6/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 127657 times.
✓ Branch 8 taken 127658 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
127659 p.get(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS],
3925 &is_enc_in_progress)) {
3926 ++m_n_errors;
3927 break;
3928 }
3929
3930 /* Get the spacename for this tablespace from the DD. */
3931
4/6
✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 127642 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 127658 times.
127674 if (dd_tablespace->files().size() != 1 &&
3932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 strcmp(space_name, sys_space_name) != 0) {
3933 /* Only the InnoDB system tablespace has support for
3934 multiple files per tablespace. For historial reasons. */
3935 ++m_n_errors;
3936 break;
3937 }
3938
3939 {
3940
1/2
✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
127658 std::lock_guard<std::mutex> guard(m_mutex);
3941
3942
6/6
✓ Branch 0 taken 81268 times.
✓ Branch 1 taken 46390 times.
✓ Branch 2 taken 69321 times.
✓ Branch 3 taken 11947 times.
✓ Branch 4 taken 69321 times.
✓ Branch 5 taken 58337 times.
127658 if (!dict_sys_t::is_reserved(space_id) && space_id > m_space_max_id) {
3943 /* Currently try to find the max space_id only.
3944 It should be able to reuse the deleted smaller ones later */
3945 69321 m_space_max_id = space_id;
3946 }
3947 127658 }
3948
3949 /* System and temp files are tracked and opened separately.
3950 Consider them validated. */
3951
3/4
✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23040 times.
✓ Branch 3 taken 104618 times.
127658 if (fsp_is_system_or_temp_tablespace(space_id)) {
3952 23040 ++m_n_validated;
3953 23040 continue;
3954 }
3955
3956 /* Get the filename for this tablespace from the DD. */
3957
3/6
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 104618 times.
✗ Branch 5 not taken.
104618 const auto file = *dd_tablespace->files().begin();
3958
2/4
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
104618 std::string dd_path{file->filename().c_str()};
3959 104618 const char *filename = dd_path.c_str();
3960
3961 /* If the trunc log file is still around, this undo tablespace needs to be
3962 rebuilt now. */
3963
3/4
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23350 times.
✓ Branch 3 taken 81268 times.
104618 if (fsp_is_undo_tablespace(space_id)) {
3964
1/2
✓ Branch 0 taken 23350 times.
✗ Branch 1 not taken.
23350 mutex_enter(&undo::ddl_mutex);
3965
1/2
✓ Branch 0 taken 23350 times.
✗ Branch 1 not taken.
23350 dberr_t err = srv_undo_tablespace_fixup(space_name, filename, space_id);
3966
1/2
✓ Branch 0 taken 23350 times.
✗ Branch 1 not taken.
23350 mutex_exit(&undo::ddl_mutex);
3967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23350 times.
23350 if (err != DB_SUCCESS) {
3968 ib::error(ER_IB_MSG_FAILED_TO_FINISH_TRUNCATE, prefix.c_str(),
3969 space_name);
3970 continue;
3971 }
3972 }
3973
3974 /* Check if IBD tablespaces exist in mem correctly. This call also adjusts
3975 the tablespace name for undo and general tablespace. We still need to check
3976 if the data files are moved. */
3977
3/4
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38434 times.
✓ Branch 3 taken 66184 times.
104618 if (fil_space_exists_in_mem(space_id, space_name, false, true)) {
3978
4/6
✓ Branch 0 taken 38434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23335 times.
✓ Branch 3 taken 15099 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 38434 times.
61769 if (fsp_is_undo_tablespace(space_id) &&
3979
2/4
✓ Branch 0 taken 23335 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23335 times.
23335 !apply_dd_undo_state(space_id, dd_tablespace)) {
3980 /* Undo tablespaces are always opened first. But in case they have
3981 been moved and the DD needs to be updated, we fall thru to the location
3982 check below. First though, update the DD tablespace state. */
3983 ib::warn(ER_IB_MSG_FAIL_TO_SAVE_SPACE_STATE, prefix.c_str(),
3984 space_name);
3985 }
3986 }
3987
3988 /* Check the file paths of IBD and Undo datafiles below. */
3989
6/10
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23350 times.
✓ Branch 3 taken 81268 times.
✓ Branch 4 taken 23350 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 23350 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 104618 times.
104618 if (!fsp_is_ibd_tablespace(space_id) && !fsp_is_undo_tablespace(space_id)) {
3990 continue;
3991 }
3992
3993 /* Check if any IBD or Undo files are moved, deleted or missing. */
3994 104618 std::string new_path;
3995
3996 /* Just in case this dictionary was ported between
3997 Windows and POSIX. */
3998 104618 Fil_path::normalize(dd_path);
3999 104618 Fil_state state = Fil_state::MATCHES;
4000
4001 104618 uint32_t fsp_flags = 0;
4002
3/6
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 104618 times.
104618 if (p.get(se_key_value[DD_SPACE_FLAGS], &fsp_flags)) {
4003 /* Failed to fetch the tablespace flags. */
4004 ++m_n_errors;
4005 break;
4006 }
4007
4008
1/2
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
104618 std::lock_guard<std::mutex> guard(m_mutex);
4009
4010
2/4
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
104618 state = fil_tablespace_path_equals(space_id, space_name, fsp_flags, dd_path,
4011 &new_path);
4012
4013
2/2
✓ Branch 0 taken 104316 times.
✓ Branch 1 taken 302 times.
104618 if (state == Fil_state::MATCHES) {
4014
1/2
✓ Branch 0 taken 104316 times.
✗ Branch 1 not taken.
104316 new_path.assign(dd_path);
4015 }
4016
4017
1/2
✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
104618 std::string space_str(space_name);
4018
4019 104618 std::string old_space;
4020 104618 bool file_name_changed = false;
4021 104618 bool file_path_changed = (state == Fil_state::MOVED);
4022
4023
4/4
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 104316 times.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 219 times.
104618 if (state == Fil_state::MATCHES || state == Fil_state::MOVED) {
4024 /* We need to update space name and table name for partitioned tables
4025 if letter case is different. */
4026
3/4
✓ Branch 0 taken 104399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 104298 times.
104399 if (fil_update_partition_name(space_id, fsp_flags, true, space_str,
4027 new_path)) {
4028 101 file_name_changed = true;
4029 101 state = Fil_state::MOVED;
4030 }
4031
4032 /* Update DD if tablespace name is corrected. */
4033
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 104254 times.
104399 if (space_str.compare(space_name) != 0) {
4034
1/2
✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
145 old_space.assign(space_name);
4035 145 space_name = space_str.c_str();
4036 145 state = Fil_state::MOVED;
4037 }
4038 }
4039
4040
3/6
✓ Branch 0 taken 104189 times.
✓ Branch 1 taken 219 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 210 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
104618 switch (state) {
4041 104189 case Fil_state::MATCHES:
4042 104189 break;
4043
4044 219 case Fil_state::MISSING:
4045
4046
5/10
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 219 times.
✗ Branch 9 not taken.
438 ib::warn(ER_IB_MSG_526) << prefix << "Tablespace " << space_id << ","
4047
3/6
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
219 << " name '" << space_name << "',"
4048
3/6
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
219 << " file '" << dd_path << "'"
4049
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 << " is missing!";
4050
4051
3/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 217 times.
219 if (fsp_is_undo_tablespace(space_id)) {
4052 /* This deserves a special error message. */
4053
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename);
4054 }
4055 219 ++m_n_missing;
4056 219 continue;
4057
4058 case Fil_state::DELETED:
4059
4060 ib::warn(ER_IB_MSG_527) << prefix << "Tablespace " << space_id << ","
4061 << " name '" << space_name << "',"
4062 << " file '" << dd_path << "'"
4063 << " was deleted!";
4064 ++m_n_deleted;
4065 continue;
4066
4067 210 case Fil_state::MOVED:
4068
2/4
✓ Branch 0 taken 210 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 210 times.
✗ Branch 3 not taken.
210 fil_add_moved_space(dd_tablespace->id(), space_id, space_name, dd_path,
4069 new_path);
4070 210 ++m_n_moved;
4071
4072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 210 times.
210 if (m_n_moved > MOVED_FILES_PRINT_THRESHOLD) {
4073 filename = new_path.c_str();
4074
4075 break;
4076 }
4077
4078
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 65 times.
210 if (!old_space.empty()) {
4079
1/2
✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
145 ib::info(ER_IB_MSG_FIL_STATE_MOVED_CORRECTED, prefix.c_str(),
4080 145 static_cast<unsigned long long>(dd_tablespace->id()),
4081
1/2
✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
290 static_cast<unsigned int>(space_id), old_space.c_str(),
4082 space_name);
4083 }
4084
4085
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 127 times.
210 if (file_path_changed) {
4086
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_PATH, prefix.c_str(),
4087 83 static_cast<unsigned long long>(dd_tablespace->id()),
4088 static_cast<unsigned int>(space_id), space_name,
4089
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
166 dd_path.c_str(), new_path.c_str());
4090
4091
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 26 times.
127 } else if (file_name_changed) {
4092
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_NAME, prefix.c_str(),
4093 101 static_cast<unsigned long long>(dd_tablespace->id()),
4094 static_cast<unsigned int>(space_id), space_name,
4095
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
202 dd_path.c_str(), new_path.c_str());
4096 }
4097
4098 210 filename = new_path.c_str();
4099
4100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 210 times.
210 if (m_n_moved == MOVED_FILES_PRINT_THRESHOLD) {
4101 ib::info(ER_IB_MSG_FIL_STATE_MOVED_TOO_MANY, prefix.c_str());
4102 }
4103 210 break;
4104
4105 case Fil_state::RENAMED:
4106 break;
4107 }
4108
4109 /* If this space is already open, we can move on to the next. */
4110
3/4
✓ Branch 0 taken 104399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38450 times.
✓ Branch 3 taken 65949 times.
104399 if (nullptr != fil_space_get(space_id)) {
4111 /* Set the autoextend_size attribute for the newly opened space. */
4112 38450 uint64_t autoextend_size{};
4113
4114
6/10
✓ Branch 0 taken 38450 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38450 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26519 times.
✓ Branch 5 taken 11931 times.
✓ Branch 6 taken 26519 times.
✓ Branch 7 taken 11931 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
103419 if (o.exists(autoextend_size_str) &&
4115
6/12
✓ Branch 0 taken 26519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26519 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26519 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 26519 times.
✓ Branch 7 taken 11931 times.
✓ Branch 8 taken 38450 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
64969 !o.get(autoextend_size_str, &autoextend_size)) {
4116
1/2
✓ Branch 0 taken 26519 times.
✗ Branch 1 not taken.
26519 ut_d(dberr_t ret =) fil_set_autoextend_size(space_id, autoextend_size);
4117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26519 times.
26519 ut_ad(ret == DB_SUCCESS);
4118 }
4119 38450 ++m_n_validated;
4120 38450 continue;
4121 38450 }
4122
4123
3/4
✓ Branch 0 taken 65949 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 65936 times.
65949 if (fsp_is_undo_tablespace(space_id)) {
4124 /* The undo space may be open with a alternate space_id */
4125 13 space_id_t space_num = undo::id2num(space_id);
4126
3/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1 times.
13 if (nullptr != undo::spaces->find(space_num)) {
4127 12 ++m_n_validated;
4128 12 continue;
4129 }
4130
4131 /* If an undo tablespace from the DD is in an unknown location,
4132 it will not yet be open. */
4133 1 undo::Tablespace undo_space(space_id);
4134
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo_space.set_space_name(space_name);
4135
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo_space.set_file_name(filename);
4136
4137
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mutex_enter(&undo::ddl_mutex);
4138
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo::spaces->x_lock();
4139
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo::use_space_id(space_id);
4140
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dberr_t err = srv_undo_tablespace_open(undo_space);
4141
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 undo::spaces->x_unlock();
4142
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mutex_exit(&undo::ddl_mutex);
4143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err != DB_SUCCESS) {
4144 ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename);
4145 }
4146 1 ++m_n_validated;
4147 1 continue;
4148 1 }
4149
4150 65936 Keyring_encryption_info keyring_encryption_info;
4151
4152 /* It's safe to pass space_name in tablename charset because
4153 filename is already in filename charset. */
4154
4/4
✓ Branch 0 taken 12145 times.
✓ Branch 1 taken 53791 times.
✓ Branch 2 taken 12133 times.
✓ Branch 3 taken 12 times.
65936 bool validate = recv_needed_recovery && srv_force_recovery == 0;
4155
1/2
✓ Branch 0 taken 65936 times.
✗ Branch 1 not taken.
65936 dberr_t err = fil_ibd_open(
4156
3/4
✓ Branch 0 taken 53803 times.
✓ Branch 1 taken 12133 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53803 times.
65936 validate || is_enc_in_progress, FIL_TYPE_TABLESPACE, space_id, fsp_flags,
4157 space_name, filename, false, false, keyring_encryption_info);
4158
4159
2/2
✓ Branch 0 taken 65667 times.
✓ Branch 1 taken 269 times.
65936 switch (err) {
4160 65667 case DB_SUCCESS: {
4161 /* Set the autoextend_size attribute for the newly opened space. */
4162 65667 uint64_t autoextend_size{};
4163
4164
6/10
✓ Branch 0 taken 65667 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65667 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 64811 times.
✓ Branch 5 taken 856 times.
✓ Branch 6 taken 64811 times.
✓ Branch 7 taken 856 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
196145 if (o.exists(autoextend_size_str) &&
4165
6/12
✓ Branch 0 taken 64811 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64811 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 64811 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 64811 times.
✓ Branch 7 taken 856 times.
✓ Branch 8 taken 65667 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
130478 !o.get(autoextend_size_str, &autoextend_size)) {
4166 ut_d(dberr_t ret =)
4167
1/2
✓ Branch 0 taken 64811 times.
✗ Branch 1 not taken.
64811 fil_set_autoextend_size(space_id, autoextend_size);
4168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64811 times.
64811 ut_ad(ret == DB_SUCCESS);
4169 }
4170 65667 ++m_n_validated;
4171 65667 break;
4172 }
4173 269 case DB_CANNOT_OPEN_FILE:
4174 case DB_WRONG_FILE_NAME:
4175 default:
4176
5/10
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 269 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 269 times.
✗ Branch 9 not taken.
269 ib::info(ER_IB_MSG_530) << prefix << "Tablespace " << space_id << ","
4177
3/6
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
269 << " name '" << space_name << "',"
4178
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 << " unable to open file"
4179
5/10
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 269 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 269 times.
✗ Branch 9 not taken.
269 << " '" << filename << "' - " << ut_strerr(err);
4180 269 ++m_n_missing;
4181 }
4182
10/12
✓ Branch 0 taken 65936 times.
✓ Branch 1 taken 38682 times.
✓ Branch 2 taken 65936 times.
✓ Branch 3 taken 38682 times.
✓ Branch 4 taken 65936 times.
✓ Branch 5 taken 38682 times.
✓ Branch 6 taken 65936 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 38682 times.
✓ Branch 9 taken 65936 times.
✓ Branch 10 taken 38682 times.
✗ Branch 11 not taken.
259346 }
4183
4184
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 mem_heap_free(heap);
4185 11531 }
4186
4187 11531 dberr_t Validate_files::validate(const DD_tablespaces &tablespaces) {
4188 11531 m_n_to_check = tablespaces.size();
4189
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 m_n_threads = fil_get_scan_threads(m_n_to_check);
4190 11531 m_start_time = std::chrono::steady_clock::now();
4191
4192
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 11517 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 3 times.
11531 if (!srv_validate_tablespace_paths && !recv_needed_recovery) {
4193
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 ib::info(ER_IB_TABLESPACE_PATH_VALIDATION_SKIPPED);
4194 }
4195
4196 using std::placeholders::_1;
4197 using std::placeholders::_2;
4198 using std::placeholders::_3;
4199
4200 std::function<void(const Validate_files::Const_iter &,
4201 const Validate_files::Const_iter &, size_t)>
4202
2/4
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
11531 check = std::bind(&Validate_files::check, this, _1, _2, _3);
4203
4204
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 par_for(PFS_NOT_INSTRUMENTED, tablespaces, m_n_threads, check);
4205
4206
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 std::ostringstream msg;
4207
2/4
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
11531 msg << "Scanned " << m_n_to_check << " tablespaces."
4208
4/8
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11531 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11531 times.
✗ Branch 7 not taken.
23062 << " Validated " << m_n_validated.load() << ".";
4209
4210
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 11487 times.
23062 if (m_n_skipped.load() > 0) {
4211
3/6
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
88 msg << " Skipped " << m_n_skipped.load() << ".";
4212 }
4213
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 11507 times.
23062 if (m_n_moved.load() > 0) {
4214
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
48 msg << " Found " << m_n_moved.load() << " moved.";
4215 }
4216
2/2
✓ Branch 0 taken 217 times.
✓ Branch 1 taken 11314 times.
23062 if (m_n_missing.load() > 0) {
4217
3/6
✓ Branch 0 taken 217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 217 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 217 times.
✗ Branch 5 not taken.
434 msg << " Found " << m_n_missing.load() << " missing.";
4218 }
4219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
23062 if (m_n_deleted.load() > 0) {
4220 msg << " Found " << m_n_deleted.load() << " deleted.";
4221 }
4222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
23062 if (m_n_errors.load() > 0) {
4223 msg << " Encountered " << m_n_errors.load() << " errors.";
4224 }
4225
3/6
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11531 times.
✗ Branch 5 not taken.
11531 ib::info(ER_IB_MSG_531) << msg.str();
4226
4227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
11531 if (failed()) {
4228 return (DB_ERROR);
4229 }
4230
4231
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 fil_set_max_space_id_if_bigger(get_space_max_id());
4232
4233
2/2
✓ Branch 0 taken 11517 times.
✓ Branch 1 taken 14 times.
11531 if (srv_validate_tablespace_paths) {
4234 11517 clone_sys->set_space_initialized();
4235 }
4236
4237 11531 return (DB_SUCCESS);
4238 11531 }
4239
4240 /** Discover all InnoDB tablespaces.
4241 @param[in,out] thd thread handle
4242 @retval true on error
4243 @retval false on success */
4244 11531 [[nodiscard]] static bool boot_tablespaces(THD *thd) {
4245
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 auto dc = dd::get_dd_client(thd);
4246
4247 using DD_tablespaces = std::vector<const dd::Tablespace *>;
4248 using Releaser = dd::cache::Dictionary_client::Auto_releaser;
4249
4250 11531 DD_tablespaces tablespaces;
4251
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 Releaser releaser(dc);
4252
4253 /* Initialize the max space_id from sys header */
4254
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 dict_sys_mutex_enter();
4255
4256
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 mtr_t mtr;
4257
4258
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 mtr_start(&mtr);
4259
4260
2/4
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
11531 space_id_t space_max_id = mtr_read_ulint(
4261 dict_hdr_get(&mtr) + DICT_HDR_MAX_SPACE_ID, MLOG_4BYTES, &mtr);
4262
4263
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 mtr_commit(&mtr);
4264
4265
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 fil_set_max_space_id_if_bigger(space_max_id);
4266
4267
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 dict_sys_mutex_exit();
4268
4269
2/4
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
11531 ib::info(ER_IB_MSG_532) << "Reading DD tablespace files";
4270
4271
2/4
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11531 times.
11531 if (dc->fetch_global_components(&tablespaces)) {
4272 /* Failed to fetch the tablespaces from the DD. */
4273
4274 return (DD_FAILURE);
4275 }
4276
4277 11531 Validate_files validator;
4278
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 dberr_t err = validator.validate(tablespaces);
4279
4280
1/2
✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
11531 return (err == DB_SUCCESS ? DD_SUCCESS : DD_FAILURE);
4281 11531 }
4282
4283 /** Create metadata for a predefined tablespace at server initialization.
4284 @param[in,out] dd_client data dictionary client
4285 @param[in] space_id InnoDB tablespace ID
4286 @param[in] flags tablespace flags
4287 @param[in] name tablespace name
4288 @param[in] filename tablespace file name
4289 @retval false on success
4290 @retval true on failure */
4291 1140 static bool predefine_tablespace(dd::cache::Dictionary_client *dd_client,
4292 space_id_t space_id, uint32_t flags,
4293 const char *name, const char *filename) {
4294 dd::Object_id dd_space_id;
4295
4296
1/2
✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
1140 return (dd_create_tablespace(dd_client, name, space_id, flags, filename,
4297 2280 false, dd_space_id));
4298 }
4299
4300 /** Check if InnoDB is in a mode where the data dictionary is read-only.
4301 @return true if srv_read_only_mode is true or if srv_force_recovery > 0 */
4302 93181 static bool innobase_is_dict_readonly() {
4303
1/2
✓ Branch 0 taken 93181 times.
✗ Branch 1 not taken.
93181 DBUG_TRACE;
4304
4/4
✓ Branch 0 taken 92978 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 92898 times.
186362 return srv_read_only_mode || srv_force_recovery > 0;
4305 93181 }
4306
4307 #ifndef UNIV_HOTBACKUP
4308 /** Update metadata for innodb_temporary tablespace at server startup.
4309 This information is used by the information_schema.files to show the
4310 filename for the temporary tablespace innodb_temporary.
4311 @param[in,out] thd THD
4312 @retval false on success
4313 @retval true on failure */
4314 11911 static bool update_innodb_temporary_metadata(THD *thd) {
4315
3/4
✓ Branch 0 taken 11911 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 11853 times.
11911 if (innobase_is_dict_readonly()) {
4316 /* Metadata cannot be updated if the server is started in read_only
4317 mode. This means that the values for innodb_temp_data_file_path and
4318 file_name in information_schema.files will not be in same. */
4319
8/16
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 58 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 58 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 58 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 58 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 58 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 58 times.
✗ Branch 15 not taken.
58 LogErr(WARNING_LEVEL, ER_SKIP_UPDATING_METADATA_IN_SE_RO_MODE,
4320 "information_schema");
4321 58 return false;
4322 }
4323
4324 /* Get the filename from srv_tmp_space */
4325
1/2
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
11853 auto fpath = srv_tmp_space.first_datafile()->filepath();
4326 11853 auto &dc = *thd->dd_client();
4327
1/2
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
11853 dd::cache::Dictionary_client::Auto_releaser releaser(&dc);
4328
1/2
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
11853 const dd::String_type tbsp_name{dict_sys_t::s_temp_space_name};
4329 11853 dd::Tablespace *tmp_tbsp{nullptr};
4330
4331
3/6
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11853 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11853 times.
✗ Branch 5 not taken.
23706 if (!dc.acquire_for_modification<dd::Tablespace>(tbsp_name, &tmp_tbsp) &&
4332
1/2
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
11853 tmp_tbsp != nullptr) {
4333
2/4
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11853 times.
11853 ut_ad(tmp_tbsp->files().size() == 1);
4334
4335 /* Get the tablespace file for innodb_temporary tablespace. */
4336 dd::Tablespace_file *dd_file =
4337
3/6
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11853 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11853 times.
✗ Branch 5 not taken.
11853 const_cast<dd::Tablespace_file *>(*(tmp_tbsp->files().begin()));
4338
4339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11853 times.
11853 ut_ad(dd_file);
4340
4341
2/4
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11853 times.
✗ Branch 3 not taken.
11853 dd_file->set_filename(fpath);
4342
4343
2/4
✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11853 times.
11853 if (dc.update(tmp_tbsp)) {
4344 /* Unable to update the metadata. */
4345 ut_d(ut_error);
4346 ut_o(return true);
4347 }
4348 } else {
4349 /* Unable to acquire innodb_temporary tablespace for modification. */
4350 ut_d(ut_error);
4351 ut_o(return true);
4352 }
4353 11853 return false;
4354 11853 }
4355 #endif /* !UNIV_HOTBACKUP */
4356
4357 /** Predefine the undo tablespace metadata at server initialization.
4358 @param[in,out] dd_client data dictionary client
4359 @retval false on success
4360 @retval true on failure */
4361 380 static bool predefine_undo_tablespaces(
4362 dd::cache::Dictionary_client *dd_client) {
4363 /** Undo tablespaces use a reserved range of tablespace ID. */
4364
2/2
✓ Branch 0 taken 760 times.
✓ Branch 1 taken 380 times.
1140 for (auto undo_space : undo::spaces->m_spaces) {
4365
1/2
✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
760 uint32_t flags = fsp_flags_init(univ_page_size, false, false, false, false);
4366
4367
2/4
✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 760 times.
760 if (predefine_tablespace(dd_client, undo_space->id(), flags,
4368 760 undo_space->space_name(),
4369
2/4
✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 760 times.
✗ Branch 3 not taken.
760 undo_space->file_name())) {
4370 return (true);
4371 }
4372 }
4373
4374 380 return (false);
4375 }
4376
4377 /** Invalidate an entry or entries for partitoined table from the dict cache.
4378 @param[in] schema_name Schema name
4379 @param[in] table_name Table name */
4380 341864 static void innobase_dict_cache_reset(const char *schema_name,
4381 const char *table_name) {
4382 char name[FN_REFLEN];
4383 341864 snprintf(name, sizeof name, "%s/%s", schema_name, table_name);
4384
4385
1/2
✓ Branch 0 taken 341864 times.
✗ Branch 1 not taken.
341864 dict_sys_mutex_enter();
4386
4387
1/2
✓ Branch 0 taken 341864 times.
✗ Branch 1 not taken.
341864 dict_table_t *table = dict_table_check_if_in_cache_low(name);
4388
4389
2/2
✓ Branch 0 taken 200762 times.
✓ Branch 1 taken 141102 times.
341864 if (table != nullptr) {
4390
1/2
✓ Branch 0 taken 200762 times.
✗ Branch 1 not taken.
200762 btr_drop_ahi_for_table(table);
4391
1/2
✓ Branch 0 taken 200762 times.
✗ Branch 1 not taken.
200762 dict_table_remove_from_cache(table);
4392
2/2
✓ Branch 0 taken 2384 times.
✓ Branch 1 taken 138718 times.
141102 } else if (strcmp(schema_name, "mysql") != 0) {
4393
1/2
✓ Branch 0 taken 2384 times.
✗ Branch 1 not taken.
2384 dict_partitioned_table_remove_from_cache(name);
4394 }
4395
4396
1/2
✓ Branch 0 taken 341864 times.
✗ Branch 1 not taken.
341864 dict_sys_mutex_exit();
4397 341864 }
4398
4399 /** Invalidate user table dict cache after Replication Plugin recovers. Table
4400 definition could be different with XA commit/rollback of DDL operations */
4401 11787 static void innobase_dict_cache_reset_tables_and_tablespaces() {
4402 11787 dict_sys_mutex_enter();
4403
4404 /* There should be no DDL/DML activity at this stage, so access
4405 the LRU chain without mutex. We only invalidates the table
4406 in LRU list */
4407
7/12
✓ Branch 0 taken 11787 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11787 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11787 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 130518 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 142305 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 130518 times.
✓ Branch 11 taken 11787 times.
142305 for (auto table : dict_sys->table_LRU.removable()) {
4408 /* Make sure table->is_dd_table is set */
4409
4410 130518 std::string db_str;
4411 130518 std::string tbl_str;
4412
2/4
✓ Branch 0 taken 130518 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 130518 times.
✗ Branch 3 not taken.
130518 dict_name::get_table(table->name.m_name, db_str, tbl_str);
4413
4414 /* TODO: Remove follow if we have better way to identify
4415 DD "system table" */
4416
1/2
✓ Branch 0 taken 7026 times.
✗ Branch 1 not taken.
137544 if (db_str.compare("mysql") == 0 || table->is_dd_table ||
4417
9/10
✓ Branch 0 taken 7026 times.
✓ Branch 1 taken 123492 times.
✓ Branch 2 taken 7026 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7025 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1501 times.
✓ Branch 7 taken 5524 times.
✓ Branch 8 taken 124994 times.
✓ Branch 9 taken 5524 times.
144569 table->is_corrupted() ||
4418 7025 DICT_TF2_FLAG_IS_SET(table, DICT_TF2_RESURRECT_PREPARED)) {
4419 124994 continue;
4420 }
4421
4422
1/2
✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
5524 table->acquire();
4423
1/2
✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
5524 btr_drop_ahi_for_table(table);
4424
1/2
✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
5524 dd_table_close(table, nullptr, nullptr, true);
4425
4426
1/2
✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
5524 dict_table_remove_from_cache(table);
4427
4/4
✓ Branch 0 taken 5524 times.
✓ Branch 1 taken 124994 times.
✓ Branch 2 taken 5524 times.
✓ Branch 3 taken 124994 times.
255512 }
4428 11787 dict_sys_mutex_exit();
4429 11787 }
4430
4431 /** Perform high-level recovery in InnoDB as part of initializing the
4432 data dictionary.
4433 @param[in] dict_recovery_mode How to do recovery
4434 @param[in] version Target DD version if a new
4435 server is being installed.
4436 Actual DD version if restarting
4437 an existing server.
4438 @retval true An error occurred.
4439 @retval false Success - no errors. */
4440 12291 static bool innobase_dict_recover(dict_recovery_mode_t dict_recovery_mode,
4441 uint version [[maybe_unused]]) {
4442 12291 THD *thd = current_thd;
4443
4444
2/3
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 11911 times.
✗ Branch 2 not taken.
12291 switch (dict_recovery_mode) {
4445 380 case DICT_RECOVERY_INITIALIZE_TABLESPACES:
4446 380 break;
4447 11911 case DICT_RECOVERY_RESTART_SERVER:
4448 [[fallthrough]];
4449 case DICT_RECOVERY_INITIALIZE_SERVER:
4450
2/2
✓ Branch 0 taken 10301 times.
✓ Branch 1 taken 1610 times.
11911 if (dict_sys->dynamic_metadata == nullptr) {
4451 20602 dict_sys->dynamic_metadata =
4452 10301 dd_table_open_on_name(thd, nullptr, "mysql/innodb_dynamic_metadata",
4453 false, DICT_ERR_IGNORE_NONE);
4454 20602 dict_persist->table_buffer =
4455 10301 ut::new_withkey<DDTableBuffer>(UT_NEW_THIS_FILE_PSI_KEY);
4456 }
4457
4458 23822 dict_sys->table_stats =
4459 11911 dd_table_open_on_name(thd, nullptr, "mysql/innodb_table_stats", false,
4460 DICT_ERR_IGNORE_NONE);
4461 23822 dict_sys->index_stats =
4462 11911 dd_table_open_on_name(thd, nullptr, "mysql/innodb_index_stats", false,
4463 DICT_ERR_IGNORE_NONE);
4464 11911 dict_sys->ddl_log = dd_table_open_on_name(
4465 thd, nullptr, "mysql/innodb_ddl_log", false, DICT_ERR_IGNORE_NONE);
4466 11911 log_ddl = ut::new_withkey<Log_DDL>(UT_NEW_THIS_FILE_PSI_KEY);
4467 }
4468
4469
3/4
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 380 times.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
12291 switch (dict_recovery_mode) {
4470 380 case DICT_RECOVERY_INITIALIZE_SERVER:
4471 380 return (false);
4472 380 case DICT_RECOVERY_INITIALIZE_TABLESPACES: {
4473
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
4474
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 dd::cache::Dictionary_client::Auto_releaser releaser(client);
4475
4476
2/4
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
380 if (predefine_tablespace(client, dict_sys_t::s_temp_space_id,
4477 srv_tmp_space.flags(),
4478 dict_sys_t::s_temp_space_name,
4479 dict_sys_t::s_temp_space_file_name)) {
4480 return (DD_FAILURE);
4481 }
4482
4483
2/4
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
380 if (predefine_undo_tablespaces(client)) {
4484 return (DD_FAILURE);
4485 }
4486
4487 380 break;
4488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 }
4489 11531 case DICT_RECOVERY_RESTART_SERVER:
4490 /* Traverse dd::tablespaces and apply/validate this metadata. */
4491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
11531 if (boot_tablespaces(thd)) {
4492 return (true);
4493 }
4494
4495 #ifndef UNIV_HOTBACKUP
4496 /* For all tablespaces for which tablespace key is to be reencrypt,
4497 do it now. */
4498 11531 fil_encryption_reencrypt(Encryption::s_tablespaces_to_reencrypt);
4499 #endif /* !UNIV_HOTBACKUP */
4500
4501 /* We might need to fix tables for CSV and MyISAM SE */
4502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
11531 if (fix_cloned_tables(thd)) {
4503 return (true);
4504 }
4505
4506 11531 srv_dict_recover_on_restart();
4507 }
4508
4509 11911 srv_start_threads(dict_recovery_mode != DICT_RECOVERY_RESTART_SERVER);
4510
4511 #ifndef UNIV_HOTBACKUP
4512 /* Update the metadata for innodb_temporary tablespace to reflect
4513 the correct filename. */
4514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11911 times.
11911 if (update_innodb_temporary_metadata(thd)) {
4515 return true;
4516 }
4517 #endif /* !UNIV_HOTBACKUP */
4518
4519 11911 return (fil_open_for_business(srv_read_only_mode) != DB_SUCCESS);
4520 }
4521
4522 /** DDL crash recovery: process the records recovered from "log_ddl" table */
4523 11787 static void innobase_post_recover() {
4524
2/2
✓ Branch 0 taken 11771 times.
✓ Branch 1 taken 16 times.
11787 if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
4525
2/4
✓ Branch 0 taken 11771 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11771 times.
11771 DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_2",
4526 srv_inject_too_many_concurrent_trxs = true;);
4527
4528
1/2
✓ Branch 0 taken 11771 times.
✗ Branch 1 not taken.
11771 dberr_t err = log_ddl->recover();
4529
4530 /* Abort post recovery startup if this is not successful. */
4531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11771 times.
11771 if (err != DB_SUCCESS) {
4532 ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_POST_RECOVER_DDL_LOG_RECOVER);
4533 }
4534 }
4535
4536
1/2
✓ Branch 0 taken 11787 times.
✗ Branch 1 not taken.
11787 fil_free_scanned_files();
4537
4538 /* If undo tablespaces are to be encrypted, encrypt them now */
4539
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 11759 times.
11787 if (srv_undo_log_encrypt) {
4540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 ut_ad(Encryption::check_keyring());
4541
4542 /* There would be at least 2 UNDO tablespaces */
4543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES);
4544
4545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (srv_read_only_mode) {
4546 ib::error(ER_IB_MSG_1051);
4547 srv_undo_log_encrypt = false;
4548 } else {
4549 /* Enable encryption for UNDO tablespaces */
4550
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 mutex_enter(&undo::ddl_mutex);
4551
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
28 if (srv_enable_undo_encryption(nullptr)) {
4552 srv_undo_log_encrypt = false;
4553 ut_d(ut_error);
4554 }
4555
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 mutex_exit(&undo::ddl_mutex);
4556
4557 /* We have to ensure that the first page of the undo tablespaces gets
4558 flushed to disk. Otherwise during recovery, since we read the first
4559 page without applying the redo logs, it will be determined that
4560 encryption is off. */
4561
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 buf_flush_sync_all_buf_pools();
4562 }
4563 }
4564
4565 /* If redo log is to be encrypted, encrypt it now */
4566
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 11755 times.
11787 if (srv_redo_log_encrypt) {
4567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 ut_ad(Encryption::check_keyring());
4568
4569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (srv_read_only_mode) {
4570 ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY);
4571 srv_redo_log_encrypt = false;
4572 } else {
4573 /* Enable encryption for REDO log */
4574
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 if (srv_enable_redo_encryption()) {
4575 srv_redo_log_encrypt = false;
4576 ut_d(ut_error);
4577 }
4578 }
4579 }
4580
4581
4/4
✓ Branch 0 taken 11747 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 11737 times.
11787 if (srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
4582 50 purge_sys->state = PURGE_STATE_DISABLED;
4583 50 return;
4584 }
4585
4586
1/2
✓ Branch 0 taken 11737 times.
✗ Branch 1 not taken.
11737 Auto_THD thd;
4587
2/4
✓ Branch 0 taken 11737 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11737 times.
11737 if (dd_tablespace_update_cache(thd.thd)) {
4588 ut_d(ut_error);
4589 }
4590
4591
1/2
✓ Branch 0 taken 11735 times.
✗ Branch 1 not taken.
11737 srv_start_threads_after_ddl_recovery();
4592
4593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11735 times.
11735 ut_a(innodb_inited);
4594
4595
2/2
✓ Branch 0 taken 11445 times.
✓ Branch 1 taken 290 times.
11735 if (!opt_initialize) {
4596
2/4
✓ Branch 0 taken 11438 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11438 times.
11445 if (!log_pfs_create_tables()) {
4597 ib::warn(ER_IB_MSG_LOG_PFS_CREATE_TABLES_FAILED);
4598 }
4599 }
4600 11728 }
4601
4602 /**
4603 Get the server version id stored in the header of the
4604 dictionary tablespace.
4605
4606 @param [out] version Version number from the DD
4607 tablespace header.
4608
4609 @retval Operation outcome, false if no error, otherwise true.
4610 */
4611 23647 static bool innobase_dict_get_server_version(uint *version) {
4612 23647 return (fsp_header_dict_get_server_version(version));
4613 }
4614
4615 /**
4616 Store the current server version number into the
4617 header of the dictionary tablespace.
4618
4619 @retval Operation outcome, false if no error, otherwise true.
4620 */
4621 165 static bool innobase_dict_set_server_version() {
4622 /* Update the server version number, but leave the space version unchanged */
4623 165 return (upgrade_space_version(dict_sys_t::s_dict_space_id, true));
4624 }
4625
4626 /** Start page tracking.
4627 @param[out] start_id LSN indicating when the tracking was started
4628 @return Operation status.
4629 @retval 0 Success
4630 @retval other ER_* mysql error. Get error details from THD. */
4631 static int innobase_page_track_start(uint64_t *start_id) {
4632 if (srv_read_only_mode) {
4633 my_error(ER_READ_ONLY_MODE, MYF(0));
4634 return ER_READ_ONLY_MODE;
4635 }
4636
4637 Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client();
4638
4639 int err = ctx->start(false, start_id);
4640
4641 return (err);
4642 }
4643
4644 /** Stop page tracking.
4645 @param[out] stop_id Stop LSN indicating when the tracking was stopped
4646 @return Operation status.
4647 @retval 0 Success
4648 @retval other ER_* mysql error. Get error details from THD. */
4649 static int innobase_page_track_stop(uint64_t *stop_id) {
4650 if (srv_read_only_mode) {
4651 my_error(ER_READ_ONLY_MODE, MYF(0));
4652 return ER_READ_ONLY_MODE;
4653 }
4654
4655 Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client();
4656
4657 int err = ctx->stop(stop_id);
4658
4659 return (err);
4660 }
4661
4662 /** Purge page tracking data.
4663 @param[in,out] purge_id Purge LSN initially indicating till where the data
4664 needs to be purged and finally updated to until where it was actually purged
4665 @return Operation status.
4666 @retval 0 Success
4667 @retval other ER_* mysql error. Get error details from THD. */
4668 static int innobase_page_track_purge(uint64_t *purge_id) {
4669 if (srv_read_only_mode) {
4670 my_error(ER_READ_ONLY_MODE, MYF(0));
4671 return ER_READ_ONLY_MODE;
4672 }
4673
4674 auto err = arch_page_sys->purge(purge_id);
4675
4676 return (err);
4677 }
4678
4679 /** Fetch tracked pages.
4680 @param[in] cbk_func callback function return page IDs
4681 @param[in] cbk_ctx caller's context for callback
4682 @param[in,out] start_id SE specific sequence number [LSN for Innodb] from
4683 where the pages tracked would be returned.
4684 @note The range might get expanded and the actual start_id used for the
4685 querying will be updated.
4686 @param[in,out] stop_id SE specific sequence number [LSN for Innodb]
4687 until where the pages tracked would be returned.
4688 @note The range might get expanded and the actual stop_id used for the
4689 querying will be updated.
4690 @param[out] buffer allocated buffer to copy page IDs
4691 @param[in] buffer_len length of buffer in bytes
4692 @return Operation status.
4693 @retval 0 Success
4694 @retval other ER_* mysql error. Get error details from THD. */
4695 static int innobase_page_track_get_page_ids(Page_Track_Callback cbk_func,
4696 void *cbk_ctx, uint64_t *start_id,
4697 uint64_t *stop_id,
4698 unsigned char *buffer,
4699 size_t buffer_len) {
4700 if (srv_read_only_mode) {
4701 my_error(ER_READ_ONLY_MODE, MYF(0));
4702 return ER_READ_ONLY_MODE;
4703 }
4704
4705 auto err =
4706 arch_page_sys->get_pages(nullptr, cbk_func, cbk_ctx, *start_id, *stop_id,
4707 buffer, static_cast<uint>(buffer_len));
4708
4709 if (err != 0) {
4710 DBUG_PRINT("page_archiver", ("Fetch Pages"));
4711 DBUG_PRINT("page_archiver", ("Can't fetch pages"));
4712 }
4713
4714 return (err);
4715 }
4716
4717 /** Fetch approximate number of tracked pages in the given range.
4718 @param[in,out] start_id SE specific sequence number [LSN for Innodb] from
4719 where the pages tracked would be returned.
4720 @note the range might get expanded and the actual start_id used for the
4721 querying will be updated.
4722 @param[in,out] stop_id SE specific sequence number [LSN for Innodb]
4723 until where the pages tracked would be returned.
4724 @note the range might get expanded and the actual stop_id used for the
4725 querying will be updated.
4726 @param[out] num_pages number of pages tracked
4727 @return Operation status.
4728 @retval 0 Success
4729 @retval other ER_* mysql error. Get error details from THD. */
4730 static int innobase_page_track_get_num_page_ids(uint64_t *start_id,
4731 uint64_t *stop_id,
4732 uint64_t *num_pages) {
4733 if (srv_read_only_mode) {
4734 my_error(ER_READ_ONLY_MODE, MYF(0));
4735 return ER_READ_ONLY_MODE;
4736 }
4737
4738 auto err = arch_page_sys->get_num_pages(*start_id, *stop_id, num_pages);
4739
4740 if (err != 0) {
4741 DBUG_PRINT("page_archiver", ("Fetch Pages"));
4742 DBUG_PRINT("page_archiver", ("Can't fetch pages"));
4743 }
4744
4745 return (err);
4746 }
4747
4748 /** Fetch the page tracking status.
4749 @param[out] status vector of a pair of (ID, bool) where ID is the
4750 start/stop point and bool is true if the ID is a start point else false */
4751 static void innobase_page_track_get_status(
4752 std::vector<std::pair<lsn_t, bool>> &status) {
4753 if (srv_read_only_mode) {
4754 my_error(ER_READ_ONLY_MODE, MYF(0));
4755 return;
4756 }
4757
4758 arch_page_sys->get_status(status);
4759 }
4760
4761 /** Gives the file extension of an InnoDB single-table tablespace. */
4762 static const char *ha_innobase_exts[] = {dot_ext[IBD], NullS};
4763
4764 /** This function checks if the given db.tablename is a system table
4765 supported by Innodb and is used as an initializer for the data member
4766 is_supported_system_table of InnoDB storage engine handlerton.
4767 Except general_log and slow_log, currently all system tables are supported
4768 by InnoDB. Please don't add any SE-specific system tables here.
4769
4770 @param is_sql_layer_system_table if the supplied db.table_name is a SQL
4771 layer system table.
4772
4773 @return whether the table name is supported */
4774
4775 1072243 static bool innobase_is_supported_system_table(const char *, const char *,
4776 bool is_sql_layer_system_table) {
4777 // Currently InnoDB does not support any other SE specific system tables.
4778 1072243 return is_sql_layer_system_table;
4779 }
4780
4781 /** Rotate the encrypted tablespace keys according to master key
4782 rotation.
4783 @return false on success, true on failure */
4784 3700 bool innobase_encryption_key_rotation() {
4785 3700 byte *master_key = nullptr;
4786 3700 bool ret = false;
4787 dberr_t err;
4788
4789 /* Pause here to try other locks while this thread holds the backup locks. */
4790
2/4
✓ Branch 0 taken 3700 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3700 times.
✗ Branch 3 not taken.
3700 DEBUG_SYNC_C("ib_pause_encryption_rotate");
4791
4792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3700 times.
3700 if (srv_read_only_mode) {
4793 my_error(ER_INNODB_READ_ONLY, MYF(0));
4794 return (true);
4795 }
4796
4797 /* Take mutex as master_key_id is going to be changed. */
4798
1/2
✓ Branch 0 taken 3700 times.
✗ Branch 1 not taken.
3700 mutex_enter(&master_key_id_mutex);
4799
4800 /* Check if keyring loaded and the currently master key
4801 can be fetched. */
4802
3/4
✓ Branch 0 taken 3700 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3573 times.
✓ Branch 3 taken 127 times.
3700 if (Encryption::get_master_key_id() != Encryption::DEFAULT_MASTER_KEY_ID) {
4803 uint32_t master_key_id;
4804
4805 3573 Encryption::get_master_key(&master_key_id, &master_key);
4806
4807
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 3468 times.
3573 if (master_key == nullptr) {
4808
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4809 105 ret = true;
4810 105 goto error_exit;
4811 }
4812
1/2
✓ Branch 0 taken 3468 times.
✗ Branch 1 not taken.
3468 my_free(master_key);
4813 }
4814
4815 3595 master_key = nullptr;
4816
4817 /* Generate the new master key. */
4818 3595 Encryption::create_master_key(&master_key);
4819
4820
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 3528 times.
3593 if (master_key == nullptr) {
4821
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4822 65 ret = true;
4823 65 goto error_exit;
4824 }
4825
4826 /* Rotate all IBD and IBU tablespace that need it. */
4827
2/4
✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3488 times.
3528 if (fil_encryption_rotate() > 0) {
4828 my_free(master_key);
4829 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4830 goto error_exit;
4831 }
4832
4833
1/2
✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
3488 err = log_encryption_on_master_key_changed(*log_sys);
4834 3488 ret = (err != DB_SUCCESS);
4835
4836 /* If rotation failure, return error */
4837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3488 times.
3488 if (ret) {
4838 my_free(master_key);
4839 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4840 goto error_exit;
4841 }
4842
4843 /* Rotate encrypted session temporary tablespaces */
4844
1/2
✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
3488 ibt::tbsp_pool->rotate_encryption_keys();
4845
4846
1/2
✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
3488 my_free(master_key);
4847
4848 3658 error_exit:
4849 /* Release the mutex. */
4850
1/2
✓ Branch 0 taken 3658 times.
✗ Branch 1 not taken.
3658 mutex_exit(&master_key_id_mutex);
4851
4852 3658 return (ret);
4853 }
4854
4855 11808 bool innobase_fix_default_table_encryption(ulong encryption_option, bool is_server_starting) {
4856
2/2
✓ Branch 0 taken 11768 times.
✓ Branch 1 taken 40 times.
11808 if (!srv_read_only_mode) {
4857 11768 return fil_crypt_set_encrypt_tables(
4858 11768 static_cast<enum_default_table_encryption>(encryption_option), is_server_starting);
4859 }
4860 40 return false;
4861 }
4862
4863 /** Fix the empty UUID of tablespaces like system, temp etc by generating
4864 a new master key and do key rotation. These tablespaces if encrypted
4865 during startup, will be encrypted with tablespace key which has empty UUID
4866 @return false on success, true on failure */
4867 11760 bool innobase_fix_tablespaces_empty_uuid() {
4868 #ifdef UNIV_DEBUG
4869 /* This API is called only after uuid is ready */
4870 11760 srv_is_uuid_ready = true;
4871 #endif /* UNIV_DEBUG */
4872
4873 /* If we are in read only mode, we cannot do rotation but it
4874 is OK */
4875
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 11720 times.
11760 if (srv_read_only_mode) {
4876 40 return (false);
4877 }
4878
4879 /* We only need to handle the case when an encrypted tablespace
4880 is created at startup. If it is > 1, it means we already have fixed
4881 the UUID */
4882
3/4
✓ Branch 0 taken 11720 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 356 times.
✓ Branch 3 taken 11364 times.
11720 if (Encryption::get_master_key_id() > 1) {
4883 356 return (false);
4884 }
4885
4886
1/2
✓ Branch 0 taken 11364 times.
✗ Branch 1 not taken.
11364 if (!default_master_key_used) {
4887 11364 return (false);
4888 }
4889
4890 byte *master_key = nullptr;
4891 uint32_t master_key_id;
4892 Encryption::get_master_key(&master_key_id, &master_key);
4893
4894 if (master_key == nullptr) {
4895 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4896 return (true);
4897 }
4898 my_free(master_key);
4899
4900 master_key = nullptr;
4901
4902 /* Generate the new master key. */
4903 Encryption::create_master_key(&master_key);
4904
4905 if (master_key == nullptr) {
4906 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
4907 return (true);
4908 }
4909
4910 /** Check if sys, temp need rotation to fix the empty uuid */
4911 space_id_vec space_ids;
4912
4913 space_ids.push_back(srv_sys_space.space_id());
4914 space_ids.push_back(srv_tmp_space.space_id());
4915 space_ids.push_back(dict_sys_t::s_dict_space_id);
4916
4917 #ifdef UNIV_DEBUG
4918 /* Currently all session temp tablespaces that use empty uuid
4919 are destroyed. So if there is encrypted sesion temp tablespace
4920 we assert here */
4921 const auto find_encrypted = [&](const ibt::Tablespace *ts) {
4922 if (ts->is_encrypted()) {
4923 ut_ad(0);
4924 }
4925 };
4926
4927 ibt::tbsp_pool->iterate_active_tbsp(find_encrypted);
4928 #endif /* UNIV_DEBUG */
4929
4930 undo::spaces->s_lock();
4931 for (auto undo_space : undo::spaces->m_spaces) {
4932 /* We already added system tablespace */
4933 if (undo_space->id() == TRX_SYS_SPACE) {
4934 continue;
4935 }
4936 space_ids.push_back(undo_space->id());
4937 }
4938 undo::spaces->s_unlock();
4939
4940 /* Rotate log tablespace */
4941
4942 my_free(master_key);
4943
4944 return (false);
4945 }
4946
4947 /** Enable or Disable SE write ahead logging.
4948 @param[in] thd connection THD
4949 @param[in] enable enable/disable redo logging
4950 @return true iff failed. */
4951 38 static bool innobase_redo_set_state(THD *thd, bool enable) {
4952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (srv_read_only_mode) {
4953 my_error(ER_INNODB_READ_ONLY, MYF(0));
4954 return (true);
4955 }
4956
4957 38 int err = 0;
4958
4959
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20 times.
38 if (enable) {
4960 18 err = mtr_t::s_logging.enable(thd);
4961 } else {
4962 20 err = mtr_t::s_logging.disable(thd);
4963 }
4964
4965
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 36 times.
38 if (err != 0) {
4966 2 return (true);
4967 }
4968
4969 36 set_srv_redo_log(enable);
4970 36 return (false);
4971 }
4972
4973 /** Return partitioning flags. */
4974 2102734 static uint innobase_partition_flags() {
4975 return (HA_CAN_EXCHANGE_PARTITION | HA_CANNOT_PARTITION_FK |
4976 2102734 HA_TRUNCATE_PARTITION_PRECLOSE);
4977 }
4978 #endif /* !UNIV_HOTBACKUP */
4979
4980 /** Update log_checksum_algorithm_ptr with a pointer to the function
4981 corresponding to whether checksums are enabled.
4982 @param[in] check whether redo log block checksums are enabled */
4983 #ifndef UNIV_HOTBACKUP
4984 static
4985 #endif /* !UNIV_HOTBACKUP */
4986 void
4987 12034 innodb_log_checksums_func_update(bool check) {
4988
2/2
✓ Branch 0 taken 12030 times.
✓ Branch 1 taken 4 times.
12034 log_checksum_algorithm_ptr.store(check ? log_block_calc_checksum_crc32
4989 : log_block_calc_checksum_none);
4990 12034 }
4991
4992 #ifndef UNIV_HOTBACKUP
4993
4994 /** Minimum expected tablespace size. (5M) */
4995 static const ulint MIN_EXPECTED_TABLESPACE_SIZE = 5 * 1024 * 1024;
4996
4997 /** Validate innodb_undo_tablespaces. Log a warning if it was set
4998 explicitly. */
4999 12033 static void innodb_undo_tablespaces_deprecate() {
5000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12033 times.
12033 if (sysvar_source_svc == nullptr) {
5001 return;
5002 }
5003
5004 static const char *variable_name = "innodb_undo_tablespaces";
5005 enum enum_variable_source source;
5006
5007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12033 times.
12033 if (sysvar_source_svc->get(variable_name,
5008
1/2
✓ Branch 0 taken 12033 times.
✗ Branch 1 not taken.
12033 static_cast<unsigned int>(strlen(variable_name)),
5009 &source)) {
5010 return;
5011 }
5012
5013
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 12025 times.
12033 if (source != COMPILED) {
5014
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 ib::warn(ER_IB_MSG_DEPRECATED_INNODB_UNDO_TABLESPACES);
5015 8 srv_undo_tablespaces = FSP_IMPLICIT_UNDO_TABLESPACES;
5016 }
5017 }
5018
5019 /** Validate innodb_parallel_doublewrite_path. Log a warning if it was set
5020 explicitly. */
5021 12027 static void innodb_parallel_doublewrite_path_deprecate() {
5022
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 if (sysvar_source_svc != nullptr) {
5023 static const char *variable_name = "innodb_parallel_doublewrite_path";
5024 enum enum_variable_source source;
5025
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 if (!sysvar_source_svc->get(
5026
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 variable_name, static_cast<unsigned int>(strlen(variable_name)),
5027 &source)) {
5028
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12026 times.
12027 if (source != COMPILED) {
5029
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DOUBLEWRITE_PATH);
5030 }
5031 }
5032 }
5033 12027 }
5034
5035 /** Validate innodb_parallel_dblwr_encrypt. Log a warning if it was set
5036 explicitly. */
5037 12030 static void innodb_parallel_dblwr_encrypt_deprecate() {
5038
1/2
✓ Branch 0 taken 12030 times.
✗ Branch 1 not taken.
12030 if (sysvar_source_svc != nullptr) {
5039 static const char *variable_name = "innodb_parallel_dblwr_encrypt";
5040 enum enum_variable_source source;
5041
1/2
✓ Branch 0 taken 12030 times.
✗ Branch 1 not taken.
12030 if (!sysvar_source_svc->get(
5042
1/2
✓ Branch 0 taken 12030 times.
✗ Branch 1 not taken.
12030 variable_name, static_cast<unsigned int>(strlen(variable_name)),
5043 &source)) {
5044
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12026 times.
12030 if (source != COMPILED) {
5045
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DBLWR_ENCRYPT);
5046 }
5047 }
5048 }
5049 12030 }
5050
5051 /** Initialize and normalize innodb_buffer_pool_size. */
5052 12027 static void innodb_buffer_pool_size_init() {
5053 #ifdef UNIV_DEBUG
5054 12027 ulong srv_buf_pool_instances_org = srv_buf_pool_instances;
5055 #endif /* UNIV_DEBUG */
5056
5057 /* If innodb_dedicated_server == ON */
5058
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12027 if (srv_dedicated_server && sysvar_source_svc != nullptr) {
5059 static const char *variable_name = "innodb_buffer_pool_size";
5060 enum enum_variable_source source;
5061 if (!sysvar_source_svc->get(
5062 variable_name, static_cast<unsigned int>(strlen(variable_name)),
5063 &source)) {
5064 if (source == COMPILED) {
5065 double server_mem = get_sys_mem();
5066
5067 if (server_mem < 1.0) {
5068 ;
5069 } else if (server_mem <= 4.0) {
5070 srv_buf_pool_size = static_cast<ulint>(server_mem * 0.5 * GB);
5071 } else
5072 srv_buf_pool_size = static_cast<ulint>(server_mem * 0.75 * GB);
5073 } else {
5074 ib::warn(ER_IB_MSG_533)
5075 << "Option innodb_dedicated_server"
5076 " is ignored for"
5077 " innodb_buffer_pool_size because"
5078 " innodb_buffer_pool_size="
5079 << srv_buf_pool_curr_size << " is specified explicitly.";
5080 }
5081 }
5082 }
5083
5084
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 12004 times.
12027 if (srv_buf_pool_size >= BUF_POOL_SIZE_THRESHOLD) {
5085
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 15 times.
23 if (srv_buf_pool_instances == srv_buf_pool_instances_default) {
5086 #if defined(_WIN32) && !defined(_WIN64)
5087 /* Do not allocate too large of a buffer pool on
5088 Windows 32-bit systems, which can have trouble
5089 allocating larger single contiguous memory blocks. */
5090 srv_buf_pool_instances =
5091 std::min(static_cast<ulong>(MAX_BUFFER_POOLS),
5092 static_cast<ulong>(srv_buf_pool_size / (128 * 1024 * 1024)));
5093 #else /* defined(_WIN32) && !defined(_WIN64) */
5094 /* Default to 8 instances when size > 1GB. */
5095 8 srv_buf_pool_instances = 8;
5096 #endif /* defined(_WIN32) && !defined(_WIN64) */
5097 }
5098 } else {
5099 /* If buffer pool is less than 1 GiB, assume fewer
5100 threads. Also use only one buffer pool instance. */
5101
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12000 times.
12004 if (srv_buf_pool_instances != srv_buf_pool_instances_default &&
5102
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 srv_buf_pool_instances != 1) {
5103 /* We can't distinguish whether the user has explicitly
5104 started mysqld with --innodb-buffer-pool-instances=0,
5105 (srv_buf_pool_instances_default is 0) or has not
5106 specified that option at all. Thus we have the
5107 limitation that if the user started with =0, we
5108 will not emit a warning here, but we should actually
5109 do so. */
5110 2 ib::info(ER_IB_MSG_534)
5111 << "Adjusting innodb_buffer_pool_instances"
5112
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " from "
5113
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 << srv_buf_pool_instances
5114 << " to 1"
5115
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " since innodb_buffer_pool_size is less than "
5116
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 << BUF_POOL_SIZE_THRESHOLD / (1024 * 1024) << " MiB";
5117 }
5118
5119 12004 srv_buf_pool_instances = 1;
5120 }
5121
5122 #ifdef UNIV_DEBUG
5123
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12026 times.
12027 if (srv_buf_pool_debug &&
5124
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 srv_buf_pool_instances_org != srv_buf_pool_instances_default) {
5125 1 srv_buf_pool_instances = srv_buf_pool_instances_org;
5126 };
5127 #endif /* UNIV_DEBUG */
5128
5129 12027 srv_buf_pool_chunk_unit = buf_pool_adjust_chunk_unit(srv_buf_pool_chunk_unit);
5130 12027 srv_buf_pool_size = buf_pool_size_align(srv_buf_pool_size);
5131
5132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_ad(srv_buf_pool_chunk_unit >= srv_buf_pool_chunk_unit_min);
5133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_ad(srv_buf_pool_chunk_unit <= srv_buf_pool_chunk_unit_max);
5134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_ad(srv_buf_pool_chunk_unit % srv_buf_pool_chunk_unit_blk_sz == 0);
5135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_ad(srv_buf_pool_chunk_unit % UNIV_PAGE_SIZE == 0);
5136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_ad(0 ==
5137 srv_buf_pool_size % (srv_buf_pool_chunk_unit * srv_buf_pool_instances));
5138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_ad(srv_buf_pool_chunk_unit * srv_buf_pool_instances <= srv_buf_pool_size);
5139
5140 12027 srv_buf_pool_curr_size = srv_buf_pool_size;
5141
5142 /* Do not enable backoff algorithm for small buffer pool. */
5143
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12025 times.
12027 if (!innodb_empty_free_list_algorithm_allowed(
5144 static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm))) {
5145 2 sql_print_information(
5146 "InnoDB: innodb_empty_free_list_algorithm has been changed to legacy "
5147 "because of small buffer pool size. In order to use backoff, "
5148 "increase buffer pool at least up to 20MB.\n");
5149 2 srv_empty_free_list_algorithm = SRV_EMPTY_FREE_LIST_LEGACY;
5150 }
5151 12027 }
5152
5153 template <size_t N>
5154 72162 static bool innodb_variable_is_set(const char (&var_name)[N]) {
5155 enum enum_variable_source source;
5156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36081 times.
72162 ut_a(sysvar_source_svc != nullptr);
5157
1/2
✓ Branch 0 taken 36081 times.
✗ Branch 1 not taken.
72162 const auto svc_result = sysvar_source_svc->get(var_name, N - 1, &source);
5158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36081 times.
72162 ut_a(!svc_result);
5159 72162 return source != COMPILED;
5160 }
5161
5162 12027 static bool innodb_redo_log_capacity_is_set() {
5163 12027 return innodb_variable_is_set("innodb_redo_log_capacity");
5164 }
5165
5166 12027 bool innodb_log_file_size_is_set() {
5167 12027 return innodb_variable_is_set("innodb_log_file_size");
5168 }
5169
5170 12027 bool innodb_log_n_files_is_set() {
5171 12027 return innodb_variable_is_set("innodb_log_files_in_group");
5172 }
5173
5174 /** Initialize srv_redo_log_capacity / srv_redo_log_capacity_used. */
5175 12027 static void innodb_redo_log_capacity_init() {
5176
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 DBUG_TRACE;
5177
5178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(MB % UNIV_PAGE_SIZE == 0);
5179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_redo_log_capacity % MB == 0);
5180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_redo_log_capacity > 0);
5181
5182 12027 srv_redo_log_capacity_used = srv_redo_log_capacity;
5183
5184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 if (sysvar_source_svc == nullptr) {
5185 return;
5186 }
5187
5188
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 const bool file_size_set = innodb_log_file_size_is_set();
5189
5190
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 const bool n_files_set = innodb_log_n_files_is_set();
5191
5192
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 bool capacity_set = innodb_redo_log_capacity_is_set();
5193
5194
2/2
✓ Branch 0 taken 11790 times.
✓ Branch 1 taken 237 times.
12027 if (capacity_set) {
5195
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11787 times.
11790 if (file_size_set) {
5196
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ib::warn(ER_IB_MSG_LOG_PARAMS_FILE_SIZE_UNUSED);
5197 }
5198
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11788 times.
11790 if (n_files_set) {
5199
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ib::warn(ER_IB_MSG_LOG_PARAMS_N_FILES_UNUSED);
5200 }
5201 } else {
5202
4/4
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 232 times.
237 if (file_size_set || n_files_set) {
5203 5 srv_redo_log_capacity_used = srv_log_file_size * srv_log_n_files;
5204 5 capacity_set = true; // do not change it in dedicated_server mode
5205
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 ib::warn(ER_IB_MSG_LOG_PARAMS_LEGACY_USAGE, srv_redo_log_capacity_used);
5206 }
5207 }
5208
5209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 if (srv_dedicated_server) {
5210 double auto_buf_pool_size_in_gb;
5211 static const char *var_name_buf_pool_size = "innodb_buffer_pool_size";
5212 enum enum_variable_source source;
5213
5214 auto_buf_pool_size_in_gb = static_cast<double>(srv_buf_pool_size / GB);
5215
5216 /* If user has set buffer pool size in .cnf, we will not use it as base
5217 line for log_file_size auto tuning, instead, we will get the value of
5218 possible tuned buffer pool size. */
5219 if (!sysvar_source_svc->get(
5220 var_name_buf_pool_size,
5221 static_cast<unsigned int>(strlen(var_name_buf_pool_size)),
5222 &source)) {
5223 if (source != COMPILED) {
5224 double server_mem = get_sys_mem();
5225
5226 #ifdef UNIV_DEBUG_DEDICATED
5227 server_mem = srv_debug_system_mem_size / GB;
5228 #endif /* UNIV_DEBUG_DEDICATED */
5229
5230 if (server_mem < 1.0) {
5231 ;
5232 } else if (server_mem <= 4.0) {
5233 auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.5);
5234 } else
5235 auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.75);
5236 }
5237 }
5238
5239 if (!capacity_set) {
5240 /* We update srv_redo_log_capacity (underlying sysvar variable),
5241 because that is what innodb_dedicated_server is expected to do. */
5242 if (auto_buf_pool_size_in_gb < 1.0) {
5243 ut_ad(srv_redo_log_capacity == 100 * 1024 * 1024);
5244 } else if (auto_buf_pool_size_in_gb < 8.0) {
5245 srv_redo_log_capacity =
5246 static_cast<ulong>(round(auto_buf_pool_size_in_gb)) * 512ULL * MB;
5247 } else if (auto_buf_pool_size_in_gb <= 128.0) {
5248 srv_redo_log_capacity =
5249 static_cast<ulong>(round(auto_buf_pool_size_in_gb * 0.75)) * GB;
5250 } else {
5251 constexpr os_offset_t LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER = 128 * GB;
5252
5253 static_assert(
5254 LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER <= LOG_CAPACITY_MAX,
5255 "Redo log capacity, for the dedicated server, is too big.");
5256
5257 srv_redo_log_capacity = LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER;
5258 }
5259 srv_redo_log_capacity_used = srv_redo_log_capacity;
5260
5261 } else {
5262 ut_a(srv_redo_log_capacity_used % MB == 0);
5263 ib::warn(ER_IB_MSG_LOG_PARAMS_DEDICATED_SERVER_IGNORED,
5264 ulonglong{srv_redo_log_capacity_used / MB});
5265 }
5266 }
5267
5268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(LOG_CAPACITY_MIN <= srv_redo_log_capacity_used);
5269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_redo_log_capacity_used <= LOG_CAPACITY_MAX);
5270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_redo_log_capacity_used % MB == 0);
5271
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 }
5272
5273 /** Initialize, validate and normalize the InnoDB startup parameters.
5274 @return failure code
5275 @retval 0 on success
5276 @retval HA_ERR_OUT_OF_MEM when out of memory
5277 @retval HA_ERR_INITIALIZATION when some parameters are out of range */
5278 12035 static int innodb_init_params() {
5279
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 DBUG_TRACE;
5280
5281 static char current_dir[3];
5282 char *default_path;
5283
5284 /* First calculate the default path for innodb_data_home_dir etc.,
5285 in case the user has not given any value. */
5286
5287 /* It's better to use current lib, to keep paths short */
5288 12035 current_dir[0] = FN_CURLIB;
5289 12035 current_dir[1] = FN_LIBCHAR;
5290 12035 current_dir[2] = 0;
5291 12035 default_path = current_dir;
5292
5293
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 std::string mysqld_datadir{default_path};
5294
5295
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 MySQL_datadir_path = Fil_path{mysqld_datadir};
5296
5297 /* Validate, normalize and interpret the InnoDB start-up parameters. */
5298
5299 /* The default dir for data files is the datadir of MySQL */
5300
5301 12035 srv_data_home =
5302
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43 times.
45 (innobase_data_home_dir == nullptr || *innobase_data_home_dir == '\0')
5303
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 11990 times.
12080 ? default_path
5304 : innobase_data_home_dir;
5305 12035 Fil_path::normalize(srv_data_home);
5306
5307 /* Validate the undo directory. */
5308
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 11987 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
12035 if (srv_undo_dir == nullptr || srv_undo_dir[0] == 0) {
5309 11987 srv_undo_dir = default_path;
5310 } else {
5311 48 Fil_path::normalize(srv_undo_dir);
5312 }
5313
5314
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 MySQL_undo_path = Fil_path{srv_undo_dir};
5315
5316
4/6
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12035 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12034 times.
12035 if (MySQL_undo_path.is_ancestor(default_path)) {
5317
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY_LOCATION);
5318 1 return HA_ERR_INITIALIZATION;
5319 }
5320
5321 /* Validate the temp directory */
5322
2/2
✓ Branch 0 taken 12027 times.
✓ Branch 1 taken 7 times.
12034 if (ibt::srv_temp_dir == nullptr) {
5323 12027 ibt::srv_temp_dir = default_path;
5324 } else {
5325 os_file_type_t type;
5326 bool exists;
5327
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 os_file_status(ibt::srv_temp_dir, &exists, &type);
5328
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
7 if (!exists || type != OS_FILE_TYPE_DIR) {
5329
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_DOESNT_EXIST)
5330
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 << "Invalid innodb_temp_tablespaces_dir: " << ibt::srv_temp_dir
5331
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 << ". Directory doesn't exist or not valid";
5332 5 return HA_ERR_INITIALIZATION;
5333 }
5334
5335
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 Fil_path temp_dir(ibt::srv_temp_dir);
5336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (temp_dir.path().empty()) {
5337 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_EMPTY)
5338 << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir
5339 << ". Path cannot be empty";
5340 return HA_ERR_INITIALIZATION;
5341 }
5342
5343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (strchr(ibt::srv_temp_dir, ';')) {
5344 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_CONTAINS_SEMICOLON)
5345 << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir
5346 << ". Path cannot contain ;";
5347 return HA_ERR_INITIALIZATION;
5348 }
5349
5350
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (MySQL_datadir_path.is_ancestor(
5351
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
8 Fil_path::get_real_path(temp_dir.path()))) {
5352
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_SUBDIR_OF_DATADIR)
5353
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 << "Invalid innodb_temp_tablespaces_dir=" << ibt::srv_temp_dir
5354
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 << ". This path should not be a subdirectory of the datadir.";
5355 2 return HA_ERR_INITIALIZATION;
5356 }
5357
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 }
5358
5359 12029 Fil_path::normalize(ibt::srv_temp_dir);
5360
5361 /* The default dir for log files is the datadir of MySQL */
5362
5363
2/2
✓ Branch 0 taken 12019 times.
✓ Branch 1 taken 10 times.
12029 if (srv_log_group_home_dir == nullptr) {
5364 12019 srv_log_group_home_dir = default_path;
5365 }
5366 12029 Fil_path::normalize(srv_log_group_home_dir);
5367
5368
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12028 times.
12029 if (strchr(srv_log_group_home_dir, ';')) {
5369
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_LOG_GROUP_HOME_DIR);
5370 1 return HA_ERR_INITIALIZATION;
5371 }
5372
5373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12028 times.
12028 if (strchr(srv_undo_dir, ';')) {
5374 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY);
5375 return HA_ERR_INITIALIZATION;
5376 }
5377
5378 if (!is_filename_allowed(srv_buf_dump_filename, strlen(srv_buf_dump_filename),
5379 false)) {
5380 log_errlog(ERROR_LEVEL, ER_INNODB_ILLEGAL_COLON_IN_POOL);
5381 return HA_ERR_INITIALIZATION;
5382 }
5383
5384 /* Check that the value of system variable innodb_page_size was
5385 set correctly. Its value was put into srv_page_size. If valid,
5386 return the associated srv_page_size_shift. */
5387 12028 srv_page_size_shift = page_size_validate(srv_page_size);
5388
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12027 times.
12028 if (!srv_page_size_shift) {
5389
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_PAGE_SIZE, srv_page_size);
5390 1 return HA_ERR_INITIALIZATION;
5391 }
5392
5393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_log_buffer_size % OS_FILE_LOG_BLOCK_SIZE == 0);
5394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_log_buffer_size > 0);
5395
5396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_log_write_ahead_size % OS_FILE_LOG_BLOCK_SIZE == 0);
5397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_a(srv_log_write_ahead_size > 0);
5398
5399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 assert(innodb_change_buffering <= IBUF_USE_ALL);
5400
5401 /* Check that interdependent parameters have sane values. */
5402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 if (srv_max_buf_pool_modified_pct < srv_max_dirty_pages_pct_lwm) {
5403 log_errlog(WARNING_LEVEL, ER_INNODB_DIRTY_WATER_MARK_NOT_LOW,
5404 srv_max_buf_pool_modified_pct);
5405 srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct;
5406 }
5407
5408
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 if (srv_max_io_capacity == SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT) {
5409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 if (srv_io_capacity >= SRV_MAX_IO_CAPACITY_LIMIT / 2) {
5410 /* Avoid overflow. */
5411 srv_max_io_capacity = SRV_MAX_IO_CAPACITY_LIMIT;
5412 } else {
5413 /* The user has not set the value. We should
5414 set it based on innodb_io_capacity. */
5415 12027 srv_max_io_capacity = std::max(2 * srv_io_capacity, 2000UL);
5416 }
5417
5418 } else if (srv_max_io_capacity < srv_io_capacity) {
5419 log_errlog(WARNING_LEVEL, ER_INNODB_IO_CAPACITY_EXCEEDS_MAX,
5420 srv_max_io_capacity);
5421 srv_io_capacity = srv_max_io_capacity;
5422 }
5423
5424
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11976 times.
12027 if (UNIV_PAGE_SIZE_DEF != srv_page_size) {
5425
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
102 ib::warn(ER_IB_MSG_538)
5426 << "innodb-page-size has been changed from the"
5427
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 " default value "
5428
4/8
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 51 times.
✗ Branch 7 not taken.
51 << UNIV_PAGE_SIZE_DEF << " to " << srv_page_size << ".";
5429 }
5430
5431
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12008 times.
12027 if (srv_log_write_ahead_size > srv_page_size) {
5432 19 srv_log_write_ahead_size = srv_page_size;
5433 } else {
5434 12008 ulong srv_log_write_ahead_size_tmp = OS_FILE_LOG_BLOCK_SIZE;
5435
5436
2/2
✓ Branch 0 taken 48032 times.
✓ Branch 1 taken 12008 times.
60040 while (srv_log_write_ahead_size_tmp < srv_log_write_ahead_size) {
5437 48032 srv_log_write_ahead_size_tmp = srv_log_write_ahead_size_tmp * 2;
5438 }
5439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12008 times.
12008 if (srv_log_write_ahead_size_tmp != srv_log_write_ahead_size) {
5440 srv_log_write_ahead_size = srv_log_write_ahead_size_tmp / 2;
5441 }
5442 }
5443
5444 12027 srv_buf_pool_size = srv_buf_pool_curr_size;
5445
5446 12027 innodb_log_checksums_func_update(srv_log_checksums);
5447
5448 #ifdef HAVE_LINUX_LARGE_PAGES
5449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 if ((os_use_large_pages = opt_large_pages)) {
5450 os_large_page_size = opt_large_page_size;
5451 }
5452 #endif /* HAVE_LINUX_LARGE_PAGES */
5453
5454 12027 row_rollback_on_timeout = innobase_rollback_on_timeout;
5455
5456
2/2
✓ Branch 0 taken 12024 times.
✓ Branch 1 taken 3 times.
12027 if (innobase_open_files < 10) {
5457 12024 innobase_open_files = 300;
5458
4/4
✓ Branch 0 taken 12001 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 11995 times.
✓ Branch 3 taken 6 times.
12024 if (srv_file_per_table && table_cache_size > 300) {
5459 11995 innobase_open_files = table_cache_size;
5460 }
5461 }
5462
5463
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12026 times.
12027 if (innobase_open_files > (long)open_files_limit) {
5464
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 ib::warn(ER_IB_MSG_539) << "innodb_open_files should not be greater"
5465
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " than the open_files_limit.\n";
5466
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (innobase_open_files > (long)table_cache_size) {
5467 1 innobase_open_files = table_cache_size;
5468 }
5469 }
5470
5471 12027 srv_innodb_status = innobase_create_status_file;
5472
5473 /* Round up ddl:fts_parser_threads to nearest power of 2 number */
5474 {
5475 12027 ulong n_parser_threads = 1;
5476
5477
2/2
✓ Branch 0 taken 12027 times.
✓ Branch 1 taken 12027 times.
24054 while (n_parser_threads < ddl::fts_parser_threads) {
5478 12027 n_parser_threads <<= 1;
5479 }
5480
5481 12027 ddl::fts_parser_threads = n_parser_threads;
5482 }
5483
5484 /* Store the default charset-collation number of this MySQL
5485 installation */
5486
5487 12027 data_mysql_default_charset_coll = (ulint)default_charset_info->number;
5488
5489 12027 innobase_commit_concurrency_init_default();
5490
5491
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 12014 times.
12027 if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
5492 13 srv_read_only_mode = true;
5493 }
5494
5495 12027 high_level_read_only =
5496
4/4
✓ Branch 0 taken 11972 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 11967 times.
12027 srv_read_only_mode || srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
5497
5498
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 11972 times.
12027 if (srv_read_only_mode) {
5499
2/4
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
55 ib::info(ER_IB_MSG_540) << "Started in read only mode";
5500
5501 /* There is no write except to intrinsic table and so turn-off
5502 doublewrite mechanism completely. */
5503 55 dblwr::g_mode = dblwr::Mode::OFF;
5504 }
5505
5506 #ifdef LINUX_NATIVE_AIO
5507
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 if (srv_use_native_aio) {
5508
2/4
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12027 times.
✗ Branch 3 not taken.
12027 ib::info(ER_IB_MSG_541) << "Using Linux native AIO";
5509 }
5510 #elif !defined _WIN32
5511 /* Currently native AIO is supported only on Windows and Linux
5512 and that also when the support is compiled in. In all other
5513 cases, we ignore the setting of innodb_use_native_aio. */
5514 srv_use_native_aio = false;
5515 #endif
5516
5517 #ifndef _WIN32
5518 /* Check if innodb_dedicated_server == ON and O_DIRECT is supported */
5519
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12027 times.
12027 if (srv_dedicated_server && sysvar_source_svc != nullptr &&
5520 os_is_o_direct_supported()) {
5521 static const char *variable_name = "innodb_flush_method";
5522 enum enum_variable_source source;
5523
5524 if (!sysvar_source_svc->get(variable_name, strlen(variable_name),
5525 &source)) {
5526 /* If innodb_flush_method is not specified explicitly */
5527 if (source == COMPILED) {
5528 innodb_flush_method = static_cast<ulong>(SRV_UNIX_O_DIRECT_NO_FSYNC);
5529 } else {
5530 ib::warn(ER_IB_MSG_542)
5531 << "Option innodb_dedicated_server"
5532 " is ignored for innodb_flush_method"
5533 "because innodb_flush_method="
5534 << innodb_flush_method_names[innodb_flush_method]
5535 << " is specified explicitly.";
5536 }
5537 }
5538 }
5539
5540 12027 srv_unix_file_flush_method =
5541 12027 static_cast<srv_unix_flush_t>(innodb_flush_method);
5542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 ut_ad(innodb_flush_method <= SRV_UNIX_O_DIRECT_NO_FSYNC);
5543 #else
5544 srv_win_file_flush_method = static_cast<srv_win_flush_t>(innodb_flush_method);
5545 ut_ad(innodb_flush_method <= SRV_WIN_IO_NORMAL);
5546 if (srv_use_native_aio) {
5547 ib::info(ER_IB_MSG_541) << "Using Windows native AIO";
5548 }
5549 #endif /* !_WIN32 */
5550
5551 /* Set the maximum number of threads which can wait for a semaphore
5552 inside InnoDB: this is the 'sync wait array' size, as well as the
5553 maximum number of threads that can wait in the 'srv_conc array' for
5554 their time to enter InnoDB. */
5555 12027 srv_max_n_threads = 100 * 1024;
5556
5557 /* This is the first time univ_page_size is used.
5558 It was initialized to 16k pages before srv_page_size was set */
5559
2/4
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12027 times.
✗ Branch 3 not taken.
12027 univ_page_size.copy_from(page_size_t(srv_page_size, srv_page_size, false));
5560
5561
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 srv_sys_space.set_space_id(TRX_SYS_SPACE);
5562
5563 /* Create the filespace flags. */
5564
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 predefined_flags = fsp_flags_init(univ_page_size, false, false, true, false);
5565 12027 fsp_flags_set_sdi(predefined_flags);
5566
5567
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 srv_sys_space.set_flags(predefined_flags);
5568
5569
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 srv_sys_space.set_name(dict_sys_t::s_sys_space_name);
5570
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 srv_sys_space.set_path(srv_data_home);
5571
5572 /* We set the temporary tablspace id later, after recovery.
5573 The temp tablespace doesn't support raw devices.
5574 Set the name and path. */
5575
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 srv_tmp_space.set_name(dict_sys_t::s_temp_space_name);
5576
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 srv_tmp_space.set_path(srv_data_home);
5577
5578 /* Create the filespace flags with the temp flag set. */
5579 uint32_t fsp_flags =
5580
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 fsp_flags_init(univ_page_size, false, false, false, true);
5581
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 srv_tmp_space.set_flags(fsp_flags);
5582
5583 /* Set buffer pool size to default for fast startup when mysqld is
5584 run with --help --verbose options. */
5585 12027 ulint srv_buf_pool_size_org = 0;
5586
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
12027 if (opt_help && opt_verbose && opt_validate_config &&
5587 srv_buf_pool_size > srv_buf_pool_def_size) {
5588 ib::warn(ER_IB_MSG_543) << "Setting innodb_buf_pool_size to "
5589 << srv_buf_pool_def_size << " for fast startup, "
5590 << "when running with --help --verbose options.";
5591 srv_buf_pool_size_org = srv_buf_pool_size;
5592 srv_buf_pool_size = srv_buf_pool_def_size;
5593 }
5594
5595
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 innodb_buffer_pool_size_init();
5596
5597
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 innodb_undo_tablespaces_deprecate();
5598
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 innodb_parallel_doublewrite_path_deprecate();
5599
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 innodb_parallel_dblwr_encrypt_deprecate();
5600
5601
1/2
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
12027 innodb_redo_log_capacity_init();
5602
5603 /* Set the original value back to show in help. */
5604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
12027 if (srv_buf_pool_size_org != 0) {
5605 srv_buf_pool_size_org = buf_pool_size_align(srv_buf_pool_size_org);
5606 srv_buf_pool_curr_size = srv_buf_pool_size_org;
5607 }
5608
5609
2/2
✓ Branch 0 taken 12014 times.
✓ Branch 1 taken 13 times.
12027 if (srv_n_page_cleaners > srv_buf_pool_instances) {
5610 /* limit of page_cleaner parallelizability
5611 is number of buffer pool instances. */
5612 12014 srv_n_page_cleaners = srv_buf_pool_instances;
5613 }
5614
5615 12027 srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
5616
5617 12027 return 0;
5618 12035 }
5619
5620 11994 long innobase_get_open_files_limit() { return innobase_open_files; }
5621 12 void innobase_set_open_files_limit(long new_limit) {
5622 12 innobase_open_files = new_limit;
5623 12 }
5624
5625 /** Perform post-commit/rollback cleanup after DDL statement
5626 @param[in,out] thd connection thread */
5627 317739 static void innobase_post_ddl(THD *thd) {
5628 /* During upgrade, etc., the log_ddl may haven't been
5629 initialized and there is nothing to do now. */
5630
2/2
✓ Branch 0 taken 304820 times.
✓ Branch 1 taken 12919 times.
317739 if (log_ddl != nullptr) {
5631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 304820 times.
304820 DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_3",
5632 srv_inject_too_many_concurrent_trxs = true;);
5633
5634 304820 dberr_t err = log_ddl->post_ddl(thd);
5635
5636 /* If this fails, do not continue startup. */
5637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 304718 times.
304718 if (err != DB_SUCCESS) {
5638 ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_DDL_LOG_FAIL_POST_DDL);
5639 }
5640 }
5641 317637 }
5642
5643 /** Initialize the InnoDB storage engine plugin.
5644 @param[in,out] p InnoDB handlerton
5645 @return error code
5646 @retval 0 on success */
5647 12035 static int innodb_init(void *p) {
5648
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 DBUG_TRACE;
5649
5650
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 acquire_plugin_services();
5651
5652 12035 handlerton *innobase_hton = (handlerton *)p;
5653 12035 innodb_hton_ptr = innobase_hton;
5654
5655 12035 innobase_hton->state = SHOW_OPTION_YES;
5656 12035 innobase_hton->db_type = DB_TYPE_INNODB;
5657 12035 innobase_hton->savepoint_offset = sizeof(trx_named_savept_t);
5658 12035 innobase_hton->close_connection = innobase_close_connection;
5659 12035 innobase_hton->kill_connection = innobase_kill_connection;
5660 12035 innobase_hton->savepoint_set = innobase_savepoint;
5661 12035 innobase_hton->savepoint_rollback = innobase_rollback_to_savepoint;
5662
5663 12035 innobase_hton->savepoint_rollback_can_release_mdl =
5664 innobase_rollback_to_savepoint_can_release_mdl;
5665
5666 12035 innobase_hton->savepoint_release = innobase_release_savepoint;
5667 12035 innobase_hton->commit = innobase_commit;
5668 12035 innobase_hton->rollback = innobase_rollback;
5669 12035 innobase_hton->prepare = innobase_xa_prepare;
5670 12035 innobase_hton->recover = innobase_xa_recover;
5671 12035 innobase_hton->recover_prepared_in_tc = innobase_xa_recover_prepared_in_tc;
5672 12035 innobase_hton->commit_by_xid = innobase_commit_by_xid;
5673 12035 innobase_hton->rollback_by_xid = innobase_rollback_by_xid;
5674 12035 innobase_hton->set_prepared_in_tc = innobase_set_prepared_in_tc;
5675 12035 innobase_hton->set_prepared_in_tc_by_xid = innobase_set_prepared_in_tc_by_xid;
5676 12035 innobase_hton->create = innobase_create_handler;
5677 12035 innobase_hton->is_valid_tablespace_name = innobase_is_valid_tablespace_name;
5678 12035 innobase_hton->alter_tablespace = innobase_alter_tablespace;
5679 12035 innobase_hton->get_tablespace_filename_ext =
5680 innobase_get_tablespace_filename_ext;
5681 12035 innobase_hton->upgrade_tablespace = dd_upgrade_tablespace;
5682 12035 innobase_hton->upgrade_space_version = upgrade_space_version;
5683 12035 innobase_hton->upgrade_logs = dd_upgrade_logs;
5684 12035 innobase_hton->finish_upgrade = dd_upgrade_finish;
5685 12035 innobase_hton->pre_dd_shutdown = innodb_pre_dd_shutdown;
5686 12035 innobase_hton->panic = innodb_shutdown;
5687 12035 innobase_hton->partition_flags = innobase_partition_flags;
5688
5689 12035 innobase_hton->start_consistent_snapshot =
5690 innobase_start_trx_and_assign_read_view;
5691 12035 innobase_hton->clone_consistent_snapshot =
5692 innobase_start_trx_and_clone_read_view;
5693
5694 12035 innobase_hton->store_binlog_info = innobase_store_binlog_info;
5695
5696 12035 innobase_hton->flush_logs = innobase_flush_logs;
5697 12035 innobase_hton->show_status = innobase_show_status;
5698 12035 innobase_hton->lock_hton_log = innobase_lock_hton_log;
5699 12035 innobase_hton->unlock_hton_log = innobase_unlock_hton_log;
5700 12035 innobase_hton->collect_hton_log_info = innobase_collect_hton_log_info;
5701 12035 innobase_hton->fill_is_table = innobase_fill_i_s_table;
5702 12035 innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS |
5703 HTON_SUPPORTS_FOREIGN_KEYS | HTON_SUPPORTS_ATOMIC_DDL |
5704 HTON_CAN_RECREATE | HTON_SUPPORTS_SECONDARY_ENGINE |
5705 HTON_SUPPORTS_TABLE_ENCRYPTION |
5706 HTON_SUPPORTS_ONLINE_BACKUPS | HTON_SUPPORTS_COMPRESSED_COLUMNS |
5707 HTON_SUPPORTS_GENERATED_INVISIBLE_PK;
5708
5709 12035 innobase_hton->replace_native_transaction_in_thd = innodb_replace_trx_in_thd;
5710 12035 innobase_hton->file_extensions = ha_innobase_exts;
5711 12035 innobase_hton->data = &innodb_api_cb;
5712 12035 innobase_hton->ddse_dict_init = innobase_ddse_dict_init;
5713
5714 12035 innobase_hton->dict_register_dd_table_id = innobase_dict_register_dd_table_id;
5715
5716 12035 innobase_hton->dict_cache_reset = innobase_dict_cache_reset;
5717 12035 innobase_hton->dict_cache_reset_tables_and_tablespaces =
5718 innobase_dict_cache_reset_tables_and_tablespaces;
5719
5720 12035 innobase_hton->dict_recover = innobase_dict_recover;
5721 12035 innobase_hton->dict_get_server_version = innobase_dict_get_server_version;
5722 12035 innobase_hton->dict_set_server_version = innobase_dict_set_server_version;
5723
5724 12035 innobase_hton->post_recover = innobase_post_recover;
5725
5726 12035 innobase_hton->is_supported_system_table = innobase_is_supported_system_table;
5727
5728 12035 innobase_hton->get_table_statistics = innobase_get_table_statistics;
5729
5730 12035 innobase_hton->get_index_column_cardinality =
5731 innobase_get_index_column_cardinality;
5732
5733 12035 innobase_hton->get_tablespace_statistics = innobase_get_tablespace_statistics;
5734 12035 innobase_hton->get_tablespace_type = innobase_get_tablespace_type;
5735 12035 innobase_hton->get_tablespace_type_by_name =
5736 innobase_get_tablespace_type_by_name;
5737
5738 12035 innobase_hton->is_tablespace_keyring_pre_v3_encrypted =
5739 innobase_is_tablespace_keyring_pre_v3_encrypted;
5740
5741 12035 innobase_hton->is_dict_readonly = innobase_is_dict_readonly;
5742
5743 12035 innobase_hton->sdi_create = dict_sdi_create;
5744 12035 innobase_hton->sdi_drop = dict_sdi_drop;
5745 12035 innobase_hton->sdi_get_keys = dict_sdi_get_keys;
5746 12035 innobase_hton->sdi_get = dict_sdi_get;
5747 12035 innobase_hton->sdi_set = dict_sdi_set;
5748 12035 innobase_hton->sdi_delete = dict_sdi_delete;
5749
5750 12035 innobase_hton->rotate_encryption_master_key =
5751 innobase_encryption_key_rotation;
5752
5753 12035 innobase_hton->fix_tablespaces_empty_uuid =
5754 innobase_fix_tablespaces_empty_uuid;
5755
5756 12035 innobase_hton->fix_default_table_encryption =
5757 innobase_fix_default_table_encryption;
5758
5759 12035 innobase_hton->redo_log_set_state = innobase_redo_set_state;
5760
5761 12035 innobase_hton->post_ddl = innobase_post_ddl;
5762
5763 /* Initialize handler clone interfaces for. */
5764
5765 12035 innobase_hton->clone_interface.clone_capability = innodb_clone_get_capability;
5766 12035 innobase_hton->clone_interface.clone_begin = innodb_clone_begin;
5767 12035 innobase_hton->clone_interface.clone_copy = innodb_clone_copy;
5768 12035 innobase_hton->clone_interface.clone_ack = innodb_clone_ack;
5769 12035 innobase_hton->clone_interface.clone_end = innodb_clone_end;
5770
5771 12035 innobase_hton->clone_interface.clone_apply_begin = innodb_clone_apply_begin;
5772 12035 innobase_hton->clone_interface.clone_apply = innodb_clone_apply;
5773 12035 innobase_hton->clone_interface.clone_apply_end = innodb_clone_apply_end;
5774
5775 12035 innobase_hton->foreign_keys_flags =
5776 HTON_FKS_WITH_PREFIX_PARENT_KEYS |
5777 HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS |
5778 HTON_FKS_WITH_EXTENDED_PARENT_KEYS;
5779
5780 12035 innobase_hton->check_fk_column_compat = innodb_check_fk_column_compat;
5781 12035 innobase_hton->fk_name_suffix = {STRING_WITH_LEN("_ibfk_")};
5782
5783 12035 innobase_hton->is_reserved_db_name = innobase_check_reserved_file_name;
5784
5785 12035 innobase_hton->page_track.start = innobase_page_track_start;
5786 12035 innobase_hton->page_track.stop = innobase_page_track_stop;
5787 12035 innobase_hton->page_track.purge = innobase_page_track_purge;
5788 12035 innobase_hton->page_track.get_page_ids = innobase_page_track_get_page_ids;
5789 12035 innobase_hton->page_track.get_num_page_ids =
5790 innobase_page_track_get_num_page_ids;
5791 12035 innobase_hton->page_track.get_status = innobase_page_track_get_status;
5792
5793 12035 innobase_hton->upgrade_get_compression_dict_data =
5794 dd_upgrade_get_compression_dict_data;
5795
5796 static_assert(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
5797
5798
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 os_file_set_umask(my_umask);
5799
5800 /* Setup the memory alloc/free tracing mechanisms before calling
5801 any functions that could possibly allocate memory. */
5802
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 ut_new_boot();
5803
5804 #ifdef HAVE_PSI_INTERFACE
5805 /* Register keys with MySQL performance schema */
5806 int count;
5807
5808 #ifdef UNIV_DEBUG
5809 /** Count of Performance Schema keys that have been registered. */
5810 12035 int global_count = 0;
5811 #endif /* UNIV_DEBUG */
5812
5813 12035 count = static_cast<int>(array_elements(all_pthread_mutexes));
5814
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_mutex_register("innodb", all_pthread_mutexes, count);
5815
5816 #ifdef UNIV_DEBUG
5817 12035 global_count += count;
5818 #endif /* UNIV_DEBUG */
5819
5820 #ifdef UNIV_PFS_MEMORY
5821 12035 count = static_cast<int>(array_elements(pfs_instrumented_innodb_memory));
5822
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_memory_register("innodb", pfs_instrumented_innodb_memory, count);
5823 #endif /* UNIV_PFS_MEMORY */
5824
5825 #ifdef UNIV_PFS_MUTEX
5826 12035 count = static_cast<int>(array_elements(all_innodb_mutexes));
5827
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_mutex_register("innodb", all_innodb_mutexes, count);
5828
5829 #ifdef UNIV_DEBUG
5830 12035 global_count += count;
5831 #endif /* UNIV_DEBUG */
5832
5833 #endif /* UNIV_PFS_MUTEX */
5834
5835 #ifdef UNIV_PFS_RWLOCK
5836 12035 count = static_cast<int>(array_elements(all_innodb_rwlocks));
5837
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_rwlock_register("innodb", all_innodb_rwlocks, count);
5838
5839 #ifdef UNIV_DEBUG
5840 12035 global_count += count;
5841 #endif /* UNIV_DEBUG */
5842
5843 #endif /* UNIV_PFS_MUTEX */
5844
5845 #ifdef UNIV_PFS_THREAD
5846 12035 count = static_cast<int>(array_elements(all_innodb_threads));
5847
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_thread_register("innodb", all_innodb_threads, count);
5848
5849 #ifdef UNIV_DEBUG
5850 12035 global_count += count;
5851 #endif /* UNIV_DEBUG */
5852
5853 #endif /* UNIV_PFS_THREAD */
5854
5855 #ifdef UNIV_PFS_IO
5856 12035 count = static_cast<int>(array_elements(all_innodb_files));
5857
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_file_register("innodb", all_innodb_files, count);
5858
5859 #ifdef UNIV_DEBUG
5860 12035 global_count += count;
5861 #endif /* UNIV_DEBUG */
5862
5863 #endif /* UNIV_PFS_IO */
5864
5865 12035 count = static_cast<int>(array_elements(all_innodb_conds));
5866
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_cond_register("innodb", all_innodb_conds, count);
5867
5868 #ifdef UNIV_DEBUG
5869 12035 global_count += count;
5870 #endif /* UNIV_DEBUG */
5871
5872
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 mysql_data_lock_register(&innodb_data_lock_inspector);
5873
5874 #ifdef UNIV_DEBUG
5875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12035 times.
12035 if (mysql_pfs_key_t::get_count() != global_count) {
5876 ib::error(ER_IB_MSG_544) << "You have created new InnoDB PFS key(s) but "
5877 << mysql_pfs_key_t::get_count() - global_count
5878 << " key(s) is/are not registered with PFS. Please"
5879 << " register the keys in PFS arrays in"
5880 << " ha_innodb.cc.";
5881
5882 return HA_ERR_INITIALIZATION;
5883 }
5884 #endif /* UNIV_DEBUG */
5885
5886 #endif /* HAVE_PSI_INTERFACE */
5887
5888
1/2
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
12035 os_event_global_init();
5889
5890
3/4
✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 12027 times.
12035 if (innodb_init_params()) {
5891
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 return innodb_init_abort();
5892 }
5893
5894 /* After this point, error handling has to use
5895 innodb_init_abort(). */
5896
5897 /* Initialize component service handles */
5898
2/4
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
12027 if (innobase::component_services::intitialize_service_handles() == false) {
5899 return innodb_init_abort();
5900 }
5901
5902
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
12027 if (srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING &&
5903 !Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist(
5904 FIL_DEFAULT_ENCRYPTION_KEY, server_uuid)) {
5905 sql_print_error(
5906 "InnoDB: cannot enable encryption, innodb_encrypt_tables is set to "
5907 "value different than OFF, but "
5908 "keyring plugin is not available");
5909 return innodb_init_abort();
5910 }
5911
5912 // We are starting encryption threads, we must lock the keyring plugins
5913
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12025 times.
12027 if (srv_n_fil_crypt_threads_requested > 0) {
5914
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 uint number_of_keyring_locked = lock_keyrings(nullptr);
5915
5916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (number_of_keyring_locked == 0) {
5917 sql_print_error(
5918 "InnoDB: cannot enable encryption threads, "
5919 "keyring plugin is not available");
5920
5921 return innodb_init_abort();
5922 }
5923
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (Encryption::is_keyring_alive() == false) {
5924 sql_print_error(
5925 "InnoDB: keyring plugin is installed but it seems it was not "
5926 "properly initialized. Cannot enable encryption threads.");
5927 unlock_keyrings(nullptr);
5928
5929 return innodb_init_abort();
5930 }
5931 }
5932
5933
2/4
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
12027 if (!srv_sys_space.parse_params(innobase_data_file_path, true)) {
5934 ib::error(ER_IB_MSG_545)
5935 << "Unable to parse innodb_data_file_path=" << innobase_data_file_path;
5936 return innodb_init_abort();
5937 }
5938
5939
3/4
✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12024 times.
12027 if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) {
5940
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 ib::error(ER_IB_MSG_546) << "Unable to parse innodb_temp_data_file_path="
5941
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 << innobase_temp_data_file_path;
5942
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 return innodb_init_abort();
5943 }
5944
5945 /* Perform all sanity check before we take action of deleting files*/
5946
3/4
✓ Branch 0 taken 12024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12023 times.
12024 if (srv_sys_space.intersection(&srv_tmp_space)) {
5947
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 log_errlog(ERROR_LEVEL, ER_INNODB_FILES_SAME, srv_tmp_space.name(),
5948 srv_sys_space.name());
5949
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return innodb_init_abort();
5950 }
5951
5952 /* Check for keyring plugin if UNDO/REDO logs are intended to be encrypted */
5953
6/6
✓ Branch 0 taken 11993 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 11961 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 12018 times.
12085 if ((srv_undo_log_encrypt || srv_redo_log_encrypt) &&
5954
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 57 times.
62 Encryption::check_keyring() == false) {
5955
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 return innodb_init_abort();
5956 }
5957
5958 12018 return 0;
5959 12035 }
5960
5961 /** De initialize the InnoDB storage engine plugin. */
5962 10400 static int innodb_deinit(MYSQL_PLUGIN plugin_info [[maybe_unused]]) {
5963 10400 release_plugin_services();
5964 10400 return 0;
5965 }
5966
5967 /** Create a hard-coded tablespace file at server initialization.
5968 @param[in] space_id fil_space_t::id
5969 @param[in] filename file name
5970 @param[in] flags tabelspace flags
5971 @retval false on success
5972 @retval true on failure */
5973 380 static bool dd_create_hardcoded(space_id_t space_id, const char *filename,
5974 ulint flags) {
5975 380 page_no_t pages = FIL_IBD_FILE_INITIAL_SIZE;
5976
5977
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 dberr_t err = fil_ibd_create(space_id, dict_sys_t::s_dd_space_name, filename,
5978 flags, pages, FIL_ENCRYPTION_DEFAULT,
5979 380 KeyringEncryptionKeyIdInfo());
5980
5981
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 if (err == DB_SUCCESS) {
5982
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 mtr_t mtr;
5983
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 mtr.start();
5984
5985
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 bool ret = fsp_header_init(space_id, pages, &mtr);
5986
5987
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 mtr.commit();
5988
5989
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 if (ret) {
5990
1/2
✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
380 btr_sdi_create_index(space_id, false);
5991 380 return (false);
5992 }
5993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 }
5994
5995 return (true);
5996 }
5997
5998 /** Open a hard-coded tablespace file at server initialization.
5999 @param[in] space_id fil_space_t::id
6000 @param[in] filename file name
6001 @param[in] flags tabelspace flags
6002 @retval false on success
6003 @retval true on failure */
6004 11540 static bool dd_open_hardcoded(space_id_t space_id, const char *filename,
6005 ulint flags) {
6006 11540 bool fail = false;
6007
1/2
✓ Branch 0 taken 11540 times.
✗ Branch 1 not taken.
11540 fil_space_t *space = fil_space_acquire_silent(space_id);
6008 11540 Keyring_encryption_info keyring_encryption_info;
6009
6010
2/2
✓ Branch 0 taken 1979 times.
✓ Branch 1 taken 9561 times.
11540 if (space != nullptr) {
6011 /* ADD SDI flag presence in predefined flags of mysql
6012 tablespace. */
6013
6014
2/4
✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1979 times.
✗ Branch 3 not taken.
3958 if (strstr(space->files.front().name, filename) != nullptr &&
6015 /* Ignore encryption flag as it might have changed */
6016
1/2
✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
1979 !((space->flags ^ flags) & ~(FSP_FLAGS_MASK_ENCRYPTION))) {
6017
1/2
✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
1979 fil_space_open_if_needed(space);
6018
6019 } else {
6020 fail = true;
6021 }
6022
6023
1/2
✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
1979 fil_space_release(space);
6024
6025
1/2
✓ Branch 0 taken 9561 times.
✗ Branch 1 not taken.
9561 } else if (fil_ibd_open(true, FIL_TYPE_TABLESPACE, space_id, flags,
6026 dict_sys_t::s_dd_space_name, filename, true,
6027
1/2
✓ Branch 0 taken 9561 times.
✗ Branch 1 not taken.
9561 false, keyring_encryption_info) == DB_SUCCESS) {
6028 /* Set fil_space_t::size, which is 0 initially. */
6029
1/2
✓ Branch 0 taken 9561 times.
✗ Branch 1 not taken.
9561 ulint size = fil_space_get_size(space_id);
6030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9561 times.
9561 ut_a(size != ULINT_UNDEFINED);
6031
6032 } else {
6033 fail = true;
6034 }
6035
6036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11540 times.
11540 if (fail) {
6037 my_error(ER_CANT_OPEN_FILE, MYF(0), filename, 0, "");
6038 }
6039
6040 11540 return (fail);
6041 }
6042
6043 /** Open or create InnoDB data files.
6044 @param[in] dict_init_mode whether to create or open the files
6045 @param[in,out] tablespaces predefined tablespaces created by the DDSE
6046 @return 0 on success, 1 on failure */
6047 12008 static int innobase_init_files(dict_init_mode_t dict_init_mode,
6048 List<const Plugin_tablespace> *tablespaces,
6049 bool &is_dd_encrypted) {
6050
1/2
✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
12008 DBUG_TRACE;
6051
6052
6/8
✓ Branch 0 taken 11715 times.
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 118 times.
✓ Branch 3 taken 11597 times.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12008 times.
12008 ut_ad(dict_init_mode == DICT_INIT_CREATE_FILES ||
6053 dict_init_mode == DICT_INIT_CHECK_FILES ||
6054 dict_init_mode == DICT_INIT_UPGRADE_57_FILES);
6055
6056 12008 bool create = (dict_init_mode == DICT_INIT_CREATE_FILES);
6057
6058 /* Check if the data files exist or not. */
6059 dberr_t err =
6060
1/2
✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
12008 srv_sys_space.check_file_spec(create, MIN_EXPECTED_TABLESPACE_SIZE);
6061
6062
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12005 times.
12008 if (err != DB_SUCCESS) {
6063
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 return innodb_init_abort();
6064 }
6065
6066 12005 srv_is_upgrade_mode = (dict_init_mode == DICT_INIT_UPGRADE_57_FILES);
6067
6068 /* Start the InnoDB server. */
6069
1/2
✓ Branch 0 taken 12004 times.
✗ Branch 1 not taken.
12005 err = srv_start(create);
6070
6071
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 11920 times.
12004 if (err != DB_SUCCESS) {
6072
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 return innodb_init_abort();
6073 }
6074
6075 11920 space_id_t upgrade_mysql_plugin_space = SPACE_UNKNOWN;
6076
6077
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 11830 times.
11920 if (srv_is_upgrade_mode) {
6078
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
90 if (!dict_sys_table_id_build()) {
6079 return innodb_init_abort();
6080 }
6081
6082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 if (trx_sys->found_prepared_trx) {
6083 ib::error(ER_DD_UPGRADE_FOUND_PREPARED_XA_TRANSACTION);
6084 return innodb_init_abort();
6085 }
6086
6087 /* Disable AHI when we start loading tables for purge.
6088 These tables are evicted anyway after purge. */
6089
6090 90 bool old_btr_search_value = btr_search_enabled;
6091 90 btr_search_enabled = false;
6092
6093 /* Load all tablespaces upfront from InnoDB Dictionary.
6094 This is needed for applying purge and ibuf from 5.7 */
6095
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
90 if (dict_load_tablespaces_for_upgrade()) {
6096 // there is a keyring v1 encrypted table - fail the upgrade
6097 ib::error(ER_UPGRADE_KEYRING_UNSUPPORTED_VERSION_ENCRYPTION);
6098 return innodb_init_abort();
6099 }
6100
6101 /* Start purge threads immediately and wait for purge to
6102 become empty. All table_ids will be adjusted by a fixed
6103 offset during upgrade. So purge cannot load a table by
6104 table_id later. Also InnoDB dictionary will be dropped
6105 during the process of upgrade. So apply all the purge
6106 now. */
6107
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 srv_start_purge_threads();
6108
6109 uint64_t rseg_history_len;
6110
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 90 times.
188 while ((rseg_history_len = trx_sys->rseg_history_len.load()) != 0) {
6111
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 ib::info(ER_IB_MSG_547)
6112
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 << "Waiting for purge to become empty:"
6113
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 << " current purge history len is " << rseg_history_len;
6114
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 sleep(1);
6115 }
6116
6117 90 srv_upgrade_old_undo_found = false;
6118
6119
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 buf_flush_sync_all_buf_pools();
6120
6121 /* We have to find the space_id of "mysql/plugin" here. i.e. before we evict
6122 the tables from cache. */
6123
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 dict_table_t *table = dict_table_open_on_name("mysql/plugin", false, true,
6124 DICT_ERR_IGNORE_NONE);
6125
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 if (table != nullptr) {
6126 90 upgrade_mysql_plugin_space = table->space;
6127
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 dict_table_close(table, false, false);
6128 }
6129
6130
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 dict_upgrade_evict_tables_cache();
6131
6132
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 dict_stats_evict_tablespaces();
6133
6134 90 btr_search_enabled = old_btr_search_value;
6135 }
6136
6137 11920 bool do_encrypt = false;
6138
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 bool ret = dict_detect_encryption_of_mysql_ibd(
6139 dict_init_mode, upgrade_mysql_plugin_space, do_encrypt);
6140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11920 times.
11920 if (!ret) {
6141 ib::error(ER_XB_MSG_4, "mysql.ibd")
6142 << "Failed to determine if mysql.ibd is encrypted. "
6143 "Have you deleted it?";
6144 return innodb_init_abort();
6145 }
6146
6147
4/6
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11920 times.
11920 if (do_encrypt && !Encryption::check_keyring()) {
6148 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
6149 return innodb_init_abort();
6150 }
6151
6152 11920 is_dd_encrypted = do_encrypt;
6153
6154 11920 const ulint dd_space_flags =
6155
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
11920 do_encrypt ? predefined_flags | FSP_FLAGS_MASK_ENCRYPTION
6156 : predefined_flags;
6157
6158 // For upgrade from 5.7, create mysql.ibd
6159 11920 create |= (dict_init_mode == DICT_INIT_UPGRADE_57_FILES);
6160
3/4
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 11540 times.
✓ Branch 2 taken 380 times.
✗ Branch 3 not taken.
11920 ret = create ? dd_create_hardcoded(dict_sys_t::s_dict_space_id,
6161 dict_sys_t::s_dd_space_file_name,
6162 dd_space_flags)
6163
1/2
✓ Branch 0 taken 11540 times.
✗ Branch 1 not taken.
11540 : dd_open_hardcoded(dict_sys_t::s_dict_space_id,
6164 dict_sys_t::s_dd_space_file_name,
6165 dd_space_flags);
6166
6167 /* Once hardcoded tablespace mysql is created or opened,
6168 prepare it along with innodb system tablespace for server.
6169 Tell server that these two hardcoded tablespaces exist. */
6170
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 if (!ret) {
6171 11920 const size_t len =
6172 30 + sizeof("id=;flags=;server_version=;space_version=;state=normal");
6173 11920 const char *fmt =
6174 "id=%u;flags=%u;server_version=%u;space_version=%u;state=normal";
6175 static char se_private_data_innodb_system[len];
6176 static char se_private_data_dd[len];
6177 11920 snprintf(se_private_data_innodb_system, len, fmt, TRX_SYS_SPACE,
6178 srv_sys_space.flags(), DD_SPACE_CURRENT_SRV_VERSION,
6179 DD_SPACE_CURRENT_SPACE_VERSION);
6180
6181 11920 snprintf(se_private_data_dd, len, fmt, dict_sys_t::s_dict_space_id,
6182 dd_space_flags, DD_SPACE_CURRENT_SRV_VERSION,
6183 DD_SPACE_CURRENT_SPACE_VERSION);
6184
6185
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
11920 const char *dd_space_options = do_encrypt ? "encryption=y" : "";
6186
6187 static Plugin_tablespace dd_space(dict_sys_t::s_dd_space_name,
6188 dd_space_options, se_private_data_dd, "",
6189
3/8
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11920 innobase_hton_name);
6190 static Plugin_tablespace::Plugin_tablespace_file dd_file(
6191
2/4
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
11920 dict_sys_t::s_dd_space_file_name, "");
6192
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 dd_space.add_file(&dd_file);
6193
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 tablespaces->push_back(&dd_space);
6194
6195
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 11916 times.
11920 const char *options = srv_sys_space.is_encrypted() ? "encryption=y" : "";
6196
6197 static Plugin_tablespace innodb(dict_sys_t::s_sys_space_name, options,
6198 se_private_data_innodb_system, "",
6199
3/8
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11920 innobase_hton_name);
6200 11920 Tablespace::files_t::const_iterator end = srv_sys_space.m_files.end();
6201 11920 Tablespace::files_t::const_iterator begin = srv_sys_space.m_files.begin();
6202
2/2
✓ Branch 0 taken 11944 times.
✓ Branch 1 taken 11920 times.
23864 for (Tablespace::files_t::const_iterator it = begin; it != end; ++it) {
6203 11944 innobase_sys_files.push_back(
6204
2/4
✓ Branch 0 taken 11944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11944 times.
✗ Branch 3 not taken.
11944 ut::new_withkey<Plugin_tablespace::Plugin_tablespace_file>(
6205 11944 UT_NEW_THIS_FILE_PSI_KEY, it->name(), ""));
6206
1/2
✓ Branch 0 taken 11944 times.
✗ Branch 1 not taken.
11944 innodb.add_file(innobase_sys_files.back());
6207 }
6208
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 tablespaces->push_back(&innodb);
6209
6210 } else {
6211 return innodb_init_abort();
6212 }
6213
6214 11920 innobase_old_blocks_pct = static_cast<uint>(
6215
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 buf_LRU_old_ratio_update(innobase_old_blocks_pct, true));
6216
6217
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 ibuf_max_size_update(srv_change_buffer_max_size);
6218
6219
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 innobase_open_tables = ut::new_<hash_table_t>(200);
6220
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 mysql_mutex_init(innobase_share_mutex_key.m_value, &innobase_share_mutex,
6221 MY_MUTEX_INIT_FAST);
6222
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 mysql_mutex_init(commit_cond_mutex_key.m_value, &commit_cond_m,
6223 MY_MUTEX_INIT_FAST);
6224
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 mysql_cond_init(commit_cond_key.m_value, &commit_cond);
6225
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 mysql_mutex_init(resume_encryption_cond_mutex_key.m_value,
6226 &resume_encryption_cond_m, MY_MUTEX_INIT_FAST);
6227
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 mysql_cond_init(resume_encryption_cond_key.m_value, &resume_encryption_cond);
6228 11920 innodb_inited = true;
6229 #ifdef MYSQL_DYNAMIC_PLUGIN
6230 if (innobase_hton != p) {
6231 innobase_hton = reinterpret_cast<handlerton *>(p);
6232 *innobase_hton = *innodb_hton_ptr;
6233 }
6234 #endif /* MYSQL_DYNAMIC_PLUGIN */
6235
6236 /* Do this as late as possible so server is fully starts up,
6237 since we might get some initial stats if user choose to turn
6238 on some counters from start up */
6239
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11918 times.
11920 if (innobase_enable_monitor_counter) {
6240
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innodb_enable_monitor_at_startup(innobase_enable_monitor_counter);
6241 }
6242
6243 /* Turn on monitor counters that are default on */
6244
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 srv_mon_default_on();
6245
6246 /* Unit Tests */
6247 #ifdef UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR
6248 unit_test_os_file_get_parent_dir();
6249 #endif /* UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR */
6250
6251 #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH
6252 test_make_filepath();
6253 #endif /*UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH */
6254
6255 #ifdef UNIV_ENABLE_DICT_STATS_TEST
6256 test_dict_stats_all();
6257 #endif /*UNIV_ENABLE_DICT_STATS_TEST */
6258
6259 #ifdef UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT
6260 #ifdef HAVE_UT_CHRONO_T
6261 test_row_raw_format_int();
6262 #endif /* HAVE_UT_CHRONO_T */
6263 #endif /* UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT */
6264
6265 11920 return 0;
6266 12007 }
6267
6268 /** Flush InnoDB redo logs to the file system.
6269 @param[in] hton InnoDB handlerton
6270 @param[in] binlog_group_flush true if we got invoked by binlog
6271 group commit during flush stage, false in other cases.
6272 @return false */
6273 5900423 static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush) {
6274
1/2
✓ Branch 0 taken 5900429 times.
✗ Branch 1 not taken.
5900423 DBUG_TRACE;
6275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5900429 times.
5900429 assert(hton == innodb_hton_ptr);
6276
6277
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 5900396 times.
5900429 if (srv_read_only_mode) {
6278 33 return false;
6279 }
6280
6281 /* If !binlog_group_flush, we got invoked by FLUSH LOGS or similar.
6282 Else, we got invoked by binlog group commit during flush stage. */
6283
6284
4/4
✓ Branch 0 taken 5826055 times.
✓ Branch 1 taken 74341 times.
✓ Branch 2 taken 87914 times.
✓ Branch 3 taken 5738141 times.
5900396 if (binlog_group_flush && srv_flush_log_at_trx_commit == 0) {
6285 /* innodb_flush_log_at_trx_commit=0
6286 (write and sync once per second).
6287 Do not flush the redo log during binlog group commit. */
6288
6289 /* This could be unsafe if we grouped at least one DDL transaction,
6290 and we removed !trx->ddl_must_flush from condition which is checked
6291 inside trx_commit_complete_for_mysql() when we decide if we could
6292 skip the flush. */
6293 87914 return false;
6294 }
6295
6296 /* Signal and wait for all GTIDs to persist on disk. */
6297
2/2
✓ Branch 0 taken 74341 times.
✓ Branch 1 taken 5738141 times.
5812482 if (!binlog_group_flush) {
6298 74341 auto &gtid_persistor = clone_sys->get_gtid_persistor();
6299
1/2
✓ Branch 0 taken 74341 times.
✗ Branch 1 not taken.
74341 gtid_persistor.wait_flush(true, true, nullptr);
6300 }
6301
6302 /* Flush the redo log buffer to the redo log file.
6303 Sync it to disc if we are in FLUSH LOGS, or if
6304 innodb_flush_log_at_trx_commit=1
6305 (write and sync at each commit). */
6306
3/4
✓ Branch 0 taken 5738141 times.
✓ Branch 1 taken 74341 times.
✓ Branch 2 taken 5812473 times.
✗ Branch 3 not taken.
11550623 log_buffer_flush_to_disk(!binlog_group_flush ||
6307
1/2
✓ Branch 0 taken 5738141 times.
✗ Branch 1 not taken.
5738141 srv_flush_log_at_trx_commit == 1);
6308
6309 5812473 return false;
6310 5900420 }
6311
6312 /** Commits a transaction in an InnoDB database. */
6313 21554964 void innobase_commit_low(trx_t *trx) /*!< in: transaction handle */
6314 {
6315
2/2
✓ Branch 0 taken 16757272 times.
✓ Branch 1 taken 4797722 times.
21554964 if (trx_is_started(trx)) {
6316 16757272 const dberr_t error [[maybe_unused]] = trx_commit_for_mysql(trx);
6317 // This is ut_ad not ut_a, because previously we did not have an assert
6318 // and nobody has noticed for a long time, so probably there is no much
6319 // harm in silencing this error. OTOH we believe it should no longer happen
6320 // after adding `true` as a second argument to TrxInInnoDB constructor call,
6321 // so we'd like to learn if the error can still happen.
6322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16757265 times.
16757256 ut_ad(DB_SUCCESS == error);
6323 }
6324 21554987 trx->will_lock = 0;
6325 21554987 }
6326
6327 /** Stores the current binlog coordinates in the trx system header
6328 @param[in] hton InnoDB handlerton
6329 @param[in] thd MySQL thread handle */
6330 80 static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept {
6331 80 DBUG_ENTER("innobase_store_binlog_info");
6332
6333 const char *file_name;
6334 unsigned long long pos;
6335 80 thd_binlog_pos(thd, &file_name, &pos);
6336
6337 80 trx_sys_write_binlog_position("", std::numeric_limits<uint64_t>::max(),
6338 file_name, pos);
6339
6340 80 innobase_flush_logs(hton, false);
6341
6342 80 DBUG_RETURN(0);
6343 }
6344
6345 /** Creates an InnoDB transaction struct for the thd if it does not yet have
6346 one. Starts a new InnoDB transaction if a transaction is not yet started. And
6347 assigns a new snapshot for a consistent read if the transaction does not yet
6348 have one.
6349 @return 0 */
6350 121 static int innobase_start_trx_and_assign_read_view(
6351 handlerton *hton, /*!< in: InnoDB handlerton */
6352 THD *thd) /*!< in: MySQL thread handle of the user for
6353 whom the transaction should be committed */
6354 {
6355
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 DBUG_TRACE;
6356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
121 assert(hton == innodb_hton_ptr);
6357
6358 /* Create a new trx struct for thd, if it does not yet have one */
6359
6360
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 trx_t *trx = check_trx_exists(thd);
6361
6362
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 TrxInInnoDB trx_in_innodb(trx);
6363
6364
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 innobase_srv_conc_force_exit_innodb(trx);
6365
6366 /* The transaction should not be active yet, start it */
6367
2/4
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 121 times.
121 ut_ad(!trx_is_started(trx));
6368
6369
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE);
6370
6371 /* Assign a read view if the transaction does not have it yet.
6372 Do this only if transaction is using REPEATABLE READ isolation
6373 level. */
6374 121 trx->isolation_level =
6375
2/4
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
121 innobase_trx_map_isolation_level(thd_get_trx_isolation(thd));
6376
6377
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) {
6378
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
121 trx_assign_read_view(trx);
6379 } else {
6380 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6381 "InnoDB: WITH CONSISTENT SNAPSHOT"
6382 " was ignored because this phrase"
6383 " can only be used with"
6384 " REPEATABLE READ isolation level.");
6385 }
6386
6387 /* Set the MySQL flag to mark that there is an active transaction */
6388
6389
2/4
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
121 innobase_register_trx(hton, current_thd, trx);
6390
6391 121 return 0;
6392 121 }
6393
6394 /** Creates an InnoDB transaction struct for the thd if it does not
6395 yet have one. Starts a new InnoDB transaction if a transaction is not
6396 yet started. And clones snapshot for a consistent read from another
6397 session, if it has one.
6398 @param[in] hton InnoDB handlerton
6399 @param[in] thd MySQL thread handle of the user for whom the
6400 transaction should be committed
6401 @param[in] from_thd MySQL thread handle of the user session from
6402 which the consistent read should be cloned
6403 @return 0 */
6404 21 static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd,
6405 THD *from_thd) {
6406
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 DBUG_ENTER("innobase_start_trx_and_clone_read_view");
6407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 assert(hton == innodb_hton_ptr);
6408
6409 /* Get transaction handle from the donor session */
6410
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 trx_t *const from_trx = thd_to_trx(from_thd);
6411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!from_trx) {
6412 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6413 "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was "
6414 "ignored because the specified session does not have "
6415 "an open transaction inside InnoDB.");
6416
6417 DBUG_RETURN(0);
6418 }
6419
6420 /* Create a new trx struct for thd, if it does not yet have one */
6421
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 trx_t *const trx = check_trx_exists(thd);
6422
6423
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 innobase_srv_conc_force_exit_innodb(trx);
6424
6425 /* If the transaction is not started yet, start it */
6426
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE);
6427
6428 /* Clone the read view from the donor transaction. Do this only if
6429 transaction is using REPEATABLE READ isolation level. */
6430 21 trx->isolation_level =
6431
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 innobase_trx_map_isolation_level(thd_get_trx_isolation(thd));
6432
6433
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if (trx->isolation_level != TRX_ISO_REPEATABLE_READ) {
6434
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6435 "InnoDB: WITH CONSISTENT SNAPSHOT was ignored because "
6436 "this phrase can only be used with REPEATABLE READ "
6437 "isolation level.");
6438 } else {
6439
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 locksys::Global_exclusive_latch_guard guard{UT_LOCATION_HERE};
6440
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 trx_sys_mutex_enter();
6441
4/8
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 trx_mutex_enter(from_trx);
6442
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 17 times.
20 if (!trx_clone_read_view(trx, from_trx)) {
6443
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
6444 "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was "
6445 "ignored because the target transaction has not "
6446 "been assigned a read view.");
6447 }
6448 20 }
6449
6450 /* Set the MySQL flag to mark that there is an active transaction */
6451
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 innobase_register_trx(hton, current_thd, trx);
6452
6453
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 DBUG_RETURN(0);
6454 }
6455
6456 /** Commits a transaction in an InnoDB database or marks an SQL statement
6457 ended.
6458 @return 0 or deadlock error if the transaction was aborted by another
6459 higher priority transaction. */
6460 31716502 static int innobase_commit(handlerton *hton, /*!< in: InnoDB handlerton */
6461 THD *thd, /*!< in: MySQL thread handle of the
6462 user for whom the transaction should
6463 be committed */
6464 bool commit_trx) /*!< in: true - commit transaction
6465 false - the current SQL statement
6466 ended */
6467 {
6468
1/2
✓ Branch 0 taken 31716551 times.
✗ Branch 1 not taken.
31716502 DBUG_TRACE;
6469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31716551 times.
31716551 assert(hton == innodb_hton_ptr);
6470
5/8
✓ Branch 0 taken 31716551 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31716550 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1353 times.
✓ Branch 5 taken 31715197 times.
✓ Branch 6 taken 1353 times.
✗ Branch 7 not taken.
31716551 DBUG_PRINT("trans", ("ending transaction"));
6471
3/4
✓ Branch 0 taken 27977985 times.
✓ Branch 1 taken 3738565 times.
✓ Branch 2 taken 27978011 times.
✗ Branch 3 not taken.
31716550 DEBUG_SYNC_C("transaction_commit_start");
6472
6473
1/2
✓ Branch 0 taken 31716551 times.
✗ Branch 1 not taken.
31716576 trx_t *trx = check_trx_exists(thd);
6474
6475 /* We are about to check if the transaction is_aborted, and if it is,
6476 then we want to rollback, and otherwise we want to proceed.
6477 However it might happen that a different transaction, which has high priority
6478 will abort our transaction just after we do the test.
6479 To prevent that, we want to set TRX_FORCE_ROLLBACK_DISABLE flag on our trx,
6480 which is checked in RecLock::make_trx_hit_list and prevents high priority
6481 transaction from killing us.
6482 One way to do that is to call TrxInInnoDB with `true` as second argument.
6483 Note that innobase_commit is called not only on "real" COMMIT, but also
6484 after each statement (with commit_trx=false), so we need some logic to decide
6485 if we really plan to perform commit during this call.
6486 */
6487 bool will_commit =
6488
2/2
✓ Branch 0 taken 29985341 times.
✓ Branch 1 taken 1731210 times.
61701905 commit_trx ||
6489
3/4
✓ Branch 0 taken 29985354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19810933 times.
✓ Branch 3 taken 10174421 times.
29985341 (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
6490
1/2
✓ Branch 0 taken 31716550 times.
✗ Branch 1 not taken.
31716564 TrxInInnoDB trx_in_innodb(trx, will_commit);
6491
6492
3/4
✓ Branch 0 taken 31716553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 31716549 times.
31716550 if (trx_in_innodb.is_aborted()) {
6493
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 innobase_rollback(hton, thd, commit_trx);
6494
6495
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd);
6496 }
6497
6498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31716541 times.
31716549 ut_ad(trx->dict_operation_lock_mode == 0);
6499
6500 /* Transaction is deregistered only in a commit or a rollback. If
6501 it is deregistered we know there cannot be resources to be freed
6502 and we could return immediately. For the time being, we play safe
6503 and do the cleanup though there should be nothing to clean up. */
6504
6505
5/8
✓ Branch 0 taken 622866 times.
✓ Branch 1 taken 31093658 times.
✓ Branch 2 taken 622870 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 622870 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 31716528 times.
31716541 if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
6506 log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE);
6507 }
6508
6509
4/4
✓ Branch 0 taken 19032531 times.
✓ Branch 1 taken 12683998 times.
✓ Branch 2 taken 5477606 times.
✓ Branch 3 taken 13554925 times.
31716529 bool read_only = trx->read_only || trx->id == 0;
6510
6511
2/2
✓ Branch 0 taken 21542116 times.
✓ Branch 1 taken 10174413 times.
31716529 if (will_commit) {
6512
4/6
✓ Branch 0 taken 21542122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 21542119 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
21542116 DBUG_EXECUTE_IF("crash_innodb_before_commit", DBUG_SUICIDE(););
6513 /* We were instructed to commit the whole transaction, or
6514 this is an SQL statement end and autocommit is on */
6515
6516 /* We need current binlog position for mysqlbackup to work. */
6517
6518
2/2
✓ Branch 0 taken 3447469 times.
✓ Branch 1 taken 18094650 times.
21542119 if (!read_only) {
6519
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3447456 times.
3447469 while (innobase_commit_concurrency > 0) {
6520
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 mysql_mutex_lock(&commit_cond_m);
6521
6522 13 ++commit_threads;
6523
6524
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (commit_threads <= innobase_commit_concurrency) {
6525
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 mysql_mutex_unlock(&commit_cond_m);
6526 13 break;
6527 }
6528
6529 --commit_threads;
6530
6531 mysql_cond_wait(&commit_cond, &commit_cond_m);
6532
6533 mysql_mutex_unlock(&commit_cond_m);
6534 }
6535
6536 /* The following call reads the binary log position of
6537 the transaction being committed.
6538
6539 Binary logging of other engines is not relevant to
6540 InnoDB as all InnoDB requires is that committing
6541 InnoDB transactions appear in the same order in the
6542 MySQL binary log as they appear in InnoDB logs, which
6543 is guaranteed by the server.
6544
6545 If the binary log is not enabled, or the transaction
6546 is not written to the binary log, the file name will
6547 be a NULL pointer. */
6548 ulonglong pos;
6549
6550
1/2
✓ Branch 0 taken 3447469 times.
✗ Branch 1 not taken.
3447469 thd_binlog_pos(thd, &trx->mysql_log_file_name, &pos);
6551
6552 3447469 trx->mysql_log_offset = static_cast<uint64_t>(pos);
6553
6554 /* Don't do write + flush right now. For group commit
6555 to work we want to do the flush later. */
6556 3447469 trx->flush_log_later = true;
6557 }
6558
6559 /* If SE needs to persist GTID we must have a transaction. */
6560
3/4
✓ Branch 0 taken 21542117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211 times.
✓ Branch 3 taken 21541906 times.
21542119 if (thd->se_persists_gtid_explicit()) {
6561
1/2
✓ Branch 0 taken 211 times.
✗ Branch 1 not taken.
211 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
6562 }
6563
6564
1/2
✓ Branch 0 taken 21542103 times.
✗ Branch 1 not taken.
21542117 innobase_commit_low(trx);
6565
6566
2/2
✓ Branch 0 taken 3447465 times.
✓ Branch 1 taken 18094638 times.
21542103 if (!read_only) {
6567 3447465 trx->flush_log_later = false;
6568
6569
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3447452 times.
3447465 if (innobase_commit_concurrency > 0) {
6570
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 mysql_mutex_lock(&commit_cond_m);
6571
6572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 ut_ad(commit_threads > 0);
6573 13 --commit_threads;
6574
6575
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 mysql_cond_signal(&commit_cond);
6576
6577
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 mysql_mutex_unlock(&commit_cond_m);
6578 }
6579 }
6580
6581 21542103 trx_deregister_from_2pc(trx);
6582
6583 /* Now do a write + flush of logs. */
6584
2/2
✓ Branch 0 taken 3447464 times.
✓ Branch 1 taken 18094624 times.
21542088 if (!read_only) {
6585
1/2
✓ Branch 0 taken 3447426 times.
✗ Branch 1 not taken.
3447464 trx_commit_complete_for_mysql(trx);
6586 }
6587
6588 } else {
6589 /* We just mark the SQL statement ended and do not do a
6590 transaction commit */
6591
6592 /* If we had reserved the auto-inc lock for some
6593 table in this SQL statement we release it now */
6594
6595
2/2
✓ Branch 0 taken 10107452 times.
✓ Branch 1 taken 66961 times.
10174413 if (!read_only) {
6596
1/2
✓ Branch 0 taken 10107462 times.
✗ Branch 1 not taken.
10107452 lock_unlock_table_autoinc(trx);
6597 }
6598
6599 /* Store the current undo_no of the transaction so that we
6600 know where to roll back if we have to roll back the next
6601 SQL statement */
6602
6603
1/2
✓ Branch 0 taken 10174421 times.
✗ Branch 1 not taken.
10174423 trx_mark_sql_stat_end(trx);
6604 }
6605
6606 /* Reset the number AUTO-INC rows required */
6607 31716471 trx->n_autoinc_rows = 0;
6608
6609 /* This is a statement level variable. */
6610 31716471 trx->fts_next_doc_id = 0;
6611
6612
1/2
✓ Branch 0 taken 31716516 times.
✗ Branch 1 not taken.
31716471 innobase_srv_conc_force_exit_innodb(trx);
6613
6614 31716516 return 0;
6615 31716520 }
6616
6617 /** Rolls back a transaction or the latest SQL statement.
6618 @return 0 or error number */
6619 721568 static int innobase_rollback(handlerton *hton, /*!< in: InnoDB handlerton */
6620 THD *thd, /*!< in: handle to the MySQL thread
6621 of the user whose transaction should
6622 be rolled back */
6623 bool rollback_trx) /*!< in: true - rollback entire
6624 transaction false - rollback the
6625 current statement only */
6626 {
6627
1/2
✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
721568 DBUG_TRACE;
6628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 721569 times.
721569 assert(hton == innodb_hton_ptr);
6629
5/8
✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 721569 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 721568 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
721569 DBUG_PRINT("trans", ("aborting transaction"));
6630
6631
1/2
✓ Branch 0 taken 721568 times.
✗ Branch 1 not taken.
721569 trx_t *trx = check_trx_exists(thd);
6632
6633
1/2
✓ Branch 0 taken 721568 times.
✗ Branch 1 not taken.
721568 TrxInInnoDB trx_in_innodb(trx);
6634
6635
6/10
✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 721249 times.
✓ Branch 3 taken 320 times.
✓ Branch 4 taken 721249 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 721249 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 721569 times.
721568 ut_ad(trx_in_innodb.is_aborted() ||
6636 (trx->dict_operation_lock_mode == 0 &&
6637 trx->dict_operation == TRX_DICT_OP_NONE));
6638
6639
1/2
✓ Branch 0 taken 721568 times.
✗ Branch 1 not taken.
721569 innobase_srv_conc_force_exit_innodb(trx);
6640
6641 /* Reset the number AUTO-INC rows required */
6642
6643 721568 trx->n_autoinc_rows = 0;
6644
6645 /* If we had reserved the auto-inc lock for some table (if
6646 we come here to roll back the latest SQL statement) we
6647 release it now before a possibly lengthy rollback */
6648
6649
3/4
✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 721249 times.
✓ Branch 3 taken 320 times.
721568 if (!trx_in_innodb.is_aborted()) {
6650
1/2
✓ Branch 0 taken 721249 times.
✗ Branch 1 not taken.
721249 lock_unlock_table_autoinc(trx);
6651 }
6652
6653 /* This is a statement level variable. */
6654
6655 721569 trx->fts_next_doc_id = 0;
6656
6657 dberr_t error;
6658
6659
4/4
✓ Branch 0 taken 712830 times.
✓ Branch 1 taken 8739 times.
✓ Branch 2 taken 714915 times.
✓ Branch 3 taken 6654 times.
1434399 if (rollback_trx ||
6660
3/4
✓ Branch 0 taken 712830 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 706176 times.
✓ Branch 3 taken 6654 times.
712830 !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
6661
1/2
✓ Branch 0 taken 714903 times.
✗ Branch 1 not taken.
714915 error = trx_rollback_for_mysql(trx);
6662
6663
2/4
✓ Branch 0 taken 714903 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 714903 times.
714903 ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx));
6664
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 714595 times.
714903 if (trx->state.load(std::memory_order_relaxed) ==
6665 TRX_STATE_FORCED_ROLLBACK) {
6666 #ifdef UNIV_DEBUG
6667 char buffer[1024];
6668
6669
1/2
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
308 ib::info(ER_IB_MSG_548)
6670
1/2
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
308 << "Forced rollback : "
6671
2/4
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
308 << thd_security_context(thd, buffer, sizeof(buffer), 512);
6672 #endif /* UNIV_DEBUG */
6673 308 trx->state.store(TRX_STATE_NOT_STARTED, std::memory_order_relaxed);
6674 }
6675
6676 714903 trx_deregister_from_2pc(trx);
6677
6678 } else {
6679
1/2
✓ Branch 0 taken 6654 times.
✗ Branch 1 not taken.
6654 error = trx_rollback_last_sql_stat_for_mysql(trx);
6680 }
6681
6682
1/2
✓ Branch 0 taken 721557 times.
✗ Branch 1 not taken.
1443114 return convert_error_code_to_mysql(error, 0, trx->mysql_thd);
6683 721557 }
6684
6685 /** Rolls back a transaction
6686 @return 0 or error number */
6687 16672429 static int innobase_rollback_trx(trx_t *trx) /*!< in: transaction */
6688 {
6689 16672429 dberr_t error = DB_SUCCESS;
6690
6691
1/2
✓ Branch 0 taken 16672681 times.
✗ Branch 1 not taken.
16672429 DBUG_TRACE;
6692
5/8
✓ Branch 0 taken 16672572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16672656 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1127 times.
✓ Branch 5 taken 16671529 times.
✓ Branch 6 taken 1127 times.
✗ Branch 7 not taken.
16672681 DBUG_PRINT("trans", ("aborting transaction"));
6693
6694
1/2
✓ Branch 0 taken 16672650 times.
✗ Branch 1 not taken.
16672656 innobase_srv_conc_force_exit_innodb(trx);
6695
6696 /* If we had reserved the auto-inc lock for some table (if
6697 we come here to roll back the latest SQL statement) we
6698 release it now before a possibly lengthy rollback */
6699
3/4
✓ Branch 0 taken 16672625 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16672618 times.
✓ Branch 3 taken 7 times.
16672650 if (!TrxInInnoDB::is_aborted(trx)) {
6700
1/2
✓ Branch 0 taken 16672635 times.
✗ Branch 1 not taken.
16672618 lock_unlock_table_autoinc(trx);
6701 }
6702
6703
2/2
✓ Branch 0 taken 386 times.
✓ Branch 1 taken 16672329 times.
16672642 if (trx_is_rseg_updated(trx)) {
6704
1/2
✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
386 error = trx_rollback_for_mysql(trx);
6705 } else {
6706 16672329 trx->will_lock = 0;
6707 }
6708
6709
1/2
✓ Branch 0 taken 16672556 times.
✗ Branch 1 not taken.
33345362 return convert_error_code_to_mysql(error, 0, trx->mysql_thd);
6710 16672556 }
6711
6712 /** Rolls back a transaction to a savepoint.
6713 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
6714 given name */
6715 7795 static int innobase_rollback_to_savepoint(
6716 handlerton *hton, /*!< in: InnoDB handlerton */
6717 THD *thd, /*!< in: handle to the MySQL thread
6718 of the user whose transaction should
6719 be rolled back to savepoint */
6720 void *savepoint) /*!< in: savepoint data */
6721 {
6722
1/2
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
7795 DBUG_TRACE;
6723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7795 times.
7795 assert(hton == innodb_hton_ptr);
6724
6725
1/2
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
7795 trx_t *trx = check_trx_exists(thd);
6726
6727
1/2
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
7795 TrxInInnoDB trx_in_innodb(trx);
6728
6729
1/2
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
7795 innobase_srv_conc_force_exit_innodb(trx);
6730
6731 /* TODO: use provided savepoint data area to store savepoint data */
6732
6733 char name[64];
6734
6735
1/2
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
7795 longlong2str((ulint)savepoint, name, 36);
6736
6737 int64_t mysql_binlog_cache_pos;
6738
6739 dberr_t error =
6740
1/2
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
7795 trx_rollback_to_savepoint_for_mysql(trx, name, &mysql_binlog_cache_pos);
6741
6742
3/4
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 7778 times.
7795 if (error == DB_SUCCESS && trx->fts_trx != nullptr) {
6743
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 fts_savepoint_rollback(trx, name);
6744 }
6745
6746
1/2
✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
15590 return convert_error_code_to_mysql(error, 0, nullptr);
6747 7795 }
6748
6749 /** Check whether innodb state allows to safely release MDL locks after
6750 rollback to savepoint.
6751 When binlog is on, MDL locks acquired after savepoint unit are not
6752 released if there are any locks held in InnoDB.
6753 @return true if it is safe, false if its not safe. */
6754 7780 static bool innobase_rollback_to_savepoint_can_release_mdl(
6755 handlerton *hton, /*!< in: InnoDB handlerton */
6756 THD *thd) /*!< in: handle to the MySQL thread
6757 of the user whose transaction should
6758 be rolled back to savepoint */
6759 {
6760
1/2
✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
7780 DBUG_TRACE;
6761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7780 times.
7780 assert(hton == innodb_hton_ptr);
6762
6763
1/2
✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
7780 trx_t *trx = check_trx_exists(thd);
6764
6765
1/2
✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
7780 TrxInInnoDB trx_in_innodb(trx);
6766
6767
2/4
✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7780 times.
7780 ut_ad(thd == current_thd);
6768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7780 times.
7780 ut_ad(trx->lock.wait_lock == nullptr);
6769
1/2
✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
15560 return UT_LIST_GET_LEN(trx->lock.trx_locks) == 0;
6770 7780 }
6771
6772 /** Release transaction savepoint name.
6773 @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the
6774 given name */
6775 117 static int innobase_release_savepoint(
6776 handlerton *hton, /*!< in: handlerton for InnoDB */
6777 THD *thd, /*!< in: handle to the MySQL thread
6778 of the user whose transaction's
6779 savepoint should be released */
6780 void *savepoint) /*!< in: savepoint data */
6781 {
6782 dberr_t error;
6783 trx_t *trx;
6784 char name[64];
6785
6786
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 DBUG_TRACE;
6787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 assert(hton == innodb_hton_ptr);
6788
6789
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 trx = check_trx_exists(thd);
6790
6791
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 TrxInInnoDB trx_in_innodb(trx);
6792
6793 /* TODO: use provided savepoint data area to store savepoint data */
6794
6795
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 longlong2str((ulint)savepoint, name, 36);
6796
6797
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 error = trx_release_savepoint_for_mysql(trx, name);
6798
6799
3/4
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 105 times.
117 if (error == DB_SUCCESS && trx->fts_trx != nullptr) {
6800
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 fts_savepoint_release(trx, name);
6801 }
6802
6803
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
234 return convert_error_code_to_mysql(error, 0, nullptr);
6804 117 }
6805
6806 /** Sets a transaction savepoint.
6807 @return always 0, that is, always succeeds */
6808 15388 static int innobase_savepoint(
6809 handlerton *hton, /*!< in: handle to the InnoDB handlerton */
6810 THD *thd, /*!< in: handle to the MySQL thread */
6811 void *savepoint) /*!< in: savepoint data */
6812 {
6813
1/2
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
15388 DBUG_TRACE;
6814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15388 times.
15388 assert(hton == innodb_hton_ptr);
6815
6816 /* In the autocommit mode there is no sense to set a savepoint
6817 (unless we are in sub-statement), so SQL layer ensures that
6818 this method is never called in such situation. */
6819
6820
1/2
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
15388 trx_t *trx = check_trx_exists(thd);
6821
6822
1/2
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
15388 TrxInInnoDB trx_in_innodb(trx);
6823
6824
1/2
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
15388 innobase_srv_conc_force_exit_innodb(trx);
6825
6826 /* Cannot happen outside of transaction */
6827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15388 times.
15388 assert(trx_is_registered_for_2pc(trx));
6828
6829 /* TODO: use provided savepoint data area to store savepoint data */
6830 char name[64];
6831
6832
1/2
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
15388 longlong2str((ulint)savepoint, name, 36);
6833
6834
1/2
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
15388 dberr_t error = trx_savepoint_for_mysql(trx, name, 0);
6835
6836
3/4
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 15336 times.
15388 if (error == DB_SUCCESS && trx->fts_trx != nullptr) {
6837
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 fts_savepoint_take(trx->fts_trx, name);
6838 }
6839
6840
1/2
✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
30776 return convert_error_code_to_mysql(error, 0, nullptr);
6841 15388 }
6842
6843 /** Frees a possible InnoDB trx object associated with the current THD.
6844 @return 0 or error number */
6845 16672527 static int innobase_close_connection(
6846 handlerton *hton, /*!< in: innobase handlerton */
6847 THD *thd) /*!< in: handle to the MySQL thread of the user
6848 whose resources should be free'd */
6849 {
6850
1/2
✓ Branch 0 taken 16672587 times.
✗ Branch 1 not taken.
16672527 DBUG_TRACE;
6851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16672587 times.
16672587 assert(hton == innodb_hton_ptr);
6852
6853
1/2
✓ Branch 0 taken 16672585 times.
✗ Branch 1 not taken.
16672587 trx_t *trx = thd_to_trx(thd);
6854 16672585 bool free_trx = false;
6855
6856 /* During server initialization MySQL layer will try to open
6857 some of the master-slave tables those residing in InnoDB.
6858 After MySQL layer is done with needed checks these tables
6859 are closed followed by invocation of close_connection on the
6860 associated thd.
6861
6862 close_connection rolls back the trx and then frees it.
6863 Once trx is freed thd should avoid maintaining reference to
6864 it else it can be classified as stale reference.
6865
6866 Re-invocation of innodb_close_connection on same thd should
6867 get trx as NULL. */
6868
6869
2/2
✓ Branch 0 taken 16672416 times.
✓ Branch 1 taken 169 times.
16672585 if (trx != nullptr) {
6870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16672396 times.
16672416 ut_ad(trx->mysql_thd == thd);
6871
1/2
✓ Branch 0 taken 16672325 times.
✗ Branch 1 not taken.
16672396 TrxInInnoDB trx_in_innodb(trx);
6872
6873
2/4
✓ Branch 0 taken 16672319 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16672319 times.
16672325 if (trx_in_innodb.is_aborted()) {
6874 while (trx_is_started(trx)) {
6875 std::this_thread::sleep_for(std::chrono::microseconds(20));
6876 }
6877 }
6878
6879
5/8
✓ Branch 0 taken 16672159 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 16672352 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16672352 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 16672359 times.
16672319 if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
6880 log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE);
6881 }
6882
6883 /* Disconnect causes rollback in the following cases:
6884 - trx is not started, or
6885 - trx is in *not* in PREPARED state, or
6886 - trx has not updated any persistent data.
6887 TODO/FIXME: it does not make sense to initiate rollback
6888 in the 1st and 3rd case. */
6889
3/4
✓ Branch 0 taken 16672342 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16672340 times.
16672359 if (trx_is_started(trx)) {
6890
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (trx_state_eq(trx, TRX_STATE_PREPARED)) {
6891
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (trx_is_redo_rseg_updated(trx)) {
6892
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_disconnect_prepared(trx);
6893 } else {
6894 trx_rollback_for_mysql(trx);
6895 trx_deregister_from_2pc(trx);
6896 free_trx = true;
6897 }
6898 } else {
6899 log_errlog(WARNING_LEVEL, ER_INNODB_CLOSING_CONNECTION_ROLLS_BACK,
6900 trx->undo_no);
6901 ut_d(ib::warn(ER_IB_MSG_549)
6902 << "trx: " << trx << " started on: "
6903 << innobase_basename(trx->start_file) << ":" << trx->start_line);
6904 innobase_rollback_trx(trx);
6905 free_trx = true;
6906 }
6907 } else {
6908
1/2
✓ Branch 0 taken 16672325 times.
✗ Branch 1 not taken.
16672340 innobase_rollback_trx(trx);
6909 16672325 free_trx = true;
6910 }
6911 16672327 }
6912
6913 /* Free trx only after TrxInInnoDB is deleted. */
6914
2/2
✓ Branch 0 taken 16672374 times.
✓ Branch 1 taken 173 times.
16672547 if (free_trx) {
6915
1/2
✓ Branch 0 taken 16672423 times.
✗ Branch 1 not taken.
16672374 trx_free_for_mysql(trx);
6916 }
6917
6918
1/2
✓ Branch 0 taken 16672604 times.
✗ Branch 1 not taken.
16672596 ut::delete_(thd_to_innodb_session(thd));
6919
6920
1/2
✓ Branch 0 taken 16672602 times.
✗ Branch 1 not taken.
16672601 thd_to_innodb_session(thd) = nullptr;
6921
6922 16672601 return 0;
6923 16672602 }
6924
6925 /** Cancel any pending lock request associated with the current THD. */
6926 1477 static void innobase_kill_connection(
6927 handlerton *hton, /*!< in: innobase handlerton */
6928 THD *thd) /*!< in: handle to the MySQL thread being
6929 killed */
6930 {
6931
1/2
✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
1477 DBUG_TRACE;
6932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1477 times.
1477 assert(hton == innodb_hton_ptr);
6933
6934
1/2
✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
1477 trx_t *trx = thd_to_trx(thd);
6935
6936
1/2
✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
1477 if (trx != nullptr) {
6937 /* Cancel a pending lock request if there are any */
6938
2/4
✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1477 times.
✗ Branch 3 not taken.
1477 lock_cancel_if_waiting_and_release({trx});
6939 }
6940 1477 }
6941
6942 /** ** InnoDB database tables
6943 *****************************************************************************/
6944
6945 /** The requested compressed page size (key_block_size)
6946 is given in kilobytes. If it is a valid number, store
6947 that value as the number of log2 shifts from 512 in
6948 zip_ssize. Zero means it is not compressed. */
6949 807 static uint32_t get_zip_shift_size(ulint key_block_size) {
6950 uint32_t zssize; /* Zip Shift Size */
6951 uint32_t kbsize; /* Key Block Size */
6952 const uint32_t zip_ssize_max =
6953 1614 std::min(static_cast<uint32_t>(UNIV_PAGE_SSIZE_MAX),
6954 807 static_cast<uint32_t>(PAGE_ZIP_SSIZE_MAX));
6955
2/2
✓ Branch 0 taken 2085 times.
✓ Branch 1 taken 19 times.
2104 for (zssize = kbsize = 1; zssize <= zip_ssize_max; zssize++, kbsize <<= 1) {
6956
2/2
✓ Branch 0 taken 788 times.
✓ Branch 1 taken 1297 times.
2085 if (kbsize == key_block_size) {
6957 788 return (zssize);
6958 }
6959 }
6960 19 return (0);
6961 }
6962
6963 /** Get real row type for the table created based on one specified by user,
6964 CREATE TABLE options and SE capabilities.
6965
6966 @note The current code in this method is redundant with/copy of code from
6967 create_table_info_t::innobase_table_flags(). This is temporary workaround.
6968 In future this method will always return ROW_TYPE_DYNAMIC
6969 (which is suitable for intrisinc temporary tables)
6970 and rely on adjusting row format in table definition at ha_innobase::create()
6971 or ha_innobase::prepare_inplace_alter_table() time.
6972 */
6973 855112 enum row_type ha_innobase::get_real_row_type(
6974 const HA_CREATE_INFO *create_info) const {
6975 855112 const bool is_temp = create_info->options & HA_LEX_CREATE_TMP_TABLE;
6976 855112 row_type rt = create_info->row_type;
6977
6978
4/4
✓ Branch 0 taken 275280 times.
✓ Branch 1 taken 579832 times.
✓ Branch 2 taken 229056 times.
✓ Branch 3 taken 46224 times.
855112 if (is_temp && (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) {
6979 229056 return (ROW_TYPE_DYNAMIC);
6980 }
6981
6982
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 187333 times.
187588 if (rt == ROW_TYPE_DEFAULT && create_info->key_block_size &&
6983
10/10
✓ Branch 0 taken 187588 times.
✓ Branch 1 taken 438468 times.
✓ Branch 2 taken 242 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 235 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 224 times.
✓ Branch 8 taken 225 times.
✓ Branch 9 taken 625831 times.
813655 get_zip_shift_size(create_info->key_block_size) && !is_temp &&
6984
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 (srv_file_per_table || tablespace_is_shared_space(create_info))) {
6985 225 rt = ROW_TYPE_COMPRESSED;
6986 }
6987
6988
4/4
✓ Branch 0 taken 437616 times.
✓ Branch 1 taken 1067 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 187361 times.
626056 switch (rt) {
6989 437616 case ROW_TYPE_REDUNDANT:
6990 case ROW_TYPE_DYNAMIC:
6991 case ROW_TYPE_COMPACT:
6992 437616 return (rt);
6993 1067 case ROW_TYPE_COMPRESSED:
6994
6/6
✓ Branch 0 taken 1023 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1010 times.
✓ Branch 4 taken 1013 times.
✓ Branch 5 taken 54 times.
1080 if (!is_temp &&
6995
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 (srv_file_per_table || tablespace_is_shared_space(create_info))) {
6996 1013 return (rt);
6997 } else {
6998 54 return (ROW_TYPE_DYNAMIC);
6999 }
7000 12 case ROW_TYPE_NOT_USED:
7001 case ROW_TYPE_FIXED:
7002 case ROW_TYPE_PAGED:
7003 12 return (ROW_TYPE_DYNAMIC);
7004 187361 case ROW_TYPE_DEFAULT:
7005 default:
7006
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 187261 times.
✗ Branch 3 not taken.
187361 switch (innodb_default_row_format) {
7007 17 case DEFAULT_ROW_FORMAT_REDUNDANT:
7008 17 return (ROW_TYPE_REDUNDANT);
7009 83 case DEFAULT_ROW_FORMAT_COMPACT:
7010 83 return (ROW_TYPE_COMPACT);
7011 187261 case DEFAULT_ROW_FORMAT_DYNAMIC:
7012 187261 return (ROW_TYPE_DYNAMIC);
7013 default:
7014 ut_d(ut_error);
7015 ut_o(return (ROW_TYPE_DYNAMIC));
7016 }
7017 }
7018 }
7019
7020 /** Get the table flags to use for the statement.
7021 @return table flags */
7022
7023 268403376 handler::Table_flags ha_innobase::table_flags() const {
7024 268403376 THD *thd = ha_thd();
7025 268405077 handler::Table_flags flags = m_int_table_flags;
7026
7027 /* If querying the table flags when no table_share is given,
7028 then we must check if the table to be created/checked is partitioned.
7029 */
7030
6/6
✓ Branch 0 taken 3044029 times.
✓ Branch 1 taken 265361048 times.
✓ Branch 2 taken 19372 times.
✓ Branch 3 taken 3024700 times.
✓ Branch 4 taken 19372 times.
✓ Branch 5 taken 268385748 times.
268405077 if (table_share == nullptr && thd_get_work_part_info(thd) != nullptr) {
7031 /* Currently ha_innopart does not support
7032 all InnoDB features such as GEOMETRY, FULLTEXT etc. */
7033 19372 flags &= ~(HA_INNOPART_DISABLED_TABLE_FLAGS);
7034 }
7035
7036 /* Temporary table provides accurate record count */
7037
2/2
✓ Branch 0 taken 265361060 times.
✓ Branch 1 taken 3044060 times.
268405120 if (table_share != nullptr &&
7038
2/2
✓ Branch 0 taken 857466 times.
✓ Branch 1 taken 264503594 times.
265361060 table_share->table_category == TABLE_CATEGORY_TEMPORARY) {
7039 857466 flags |= HA_STATS_RECORDS_IS_EXACT;
7040 }
7041
7042 /* Need to use tx_isolation here since table flags is (also)
7043 called before prebuilt is inited. */
7044
7045 268405120 ulong const tx_isolation = thd_tx_isolation(thd);
7046
7047
2/2
✓ Branch 0 taken 164710370 times.
✓ Branch 1 taken 103694614 times.
268404984 if (tx_isolation <= ISO_READ_COMMITTED) {
7048 164710370 return (flags);
7049 }
7050
7051 103694614 return (flags | HA_BINLOG_STMT_CAPABLE);
7052 }
7053
7054 /** Returns the table type (storage engine name).
7055 @return table type */
7056
7057 147044 const char *ha_innobase::table_type() const { return (innobase_hton_name); }
7058
7059 /** Returns the operations supported for indexes.
7060 @return flags of supported operations */
7061
7062 45938833 ulong ha_innobase::index_flags(uint key, uint, bool) const {
7063
2/2
✓ Branch 0 taken 17639 times.
✓ Branch 1 taken 45921194 times.
45938833 if (table_share->key_info[key].algorithm == HA_KEY_ALG_FULLTEXT) {
7064 17639 return (0);
7065 }
7066
7067 45921194 ulong flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE |
7068 HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN;
7069
7070 /* For spatial index, we don't support descending scan
7071 and ICP so far. */
7072
2/2
✓ Branch 0 taken 29388 times.
✓ Branch 1 taken 45891806 times.
45921194 if (table_share->key_info[key].flags & HA_SPATIAL) {
7073 29388 flags = HA_READ_NEXT | HA_READ_ORDER | HA_READ_RANGE | HA_KEYREAD_ONLY |
7074 HA_KEY_SCAN_NOT_ROR;
7075 29388 return (flags);
7076 }
7077
7078 /* For dd tables mysql.*, we disable ICP for them,
7079 it's for avoiding recusively access same page. */
7080 /* TODO: Remove these code once the recursiveely access issue which
7081 caused by ICP fixed. */
7082 45891806 const char *dbname = table_share->db.str;
7083
4/4
✓ Branch 0 taken 43735436 times.
✓ Branch 1 taken 2156370 times.
✓ Branch 2 taken 33138311 times.
✓ Branch 3 taken 10597125 times.
45891806 if (dbname && strstr(dbname, dict_sys_t::s_dd_space_name) != nullptr &&
7084
2/2
✓ Branch 0 taken 32908942 times.
✓ Branch 1 taken 229369 times.
33138311 strlen(dbname) == 5) {
7085 32908942 flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE |
7086 HA_KEYREAD_ONLY;
7087 }
7088
7089 /* Multi-valued keys don't support ordered retrieval, neither they're
7090 suitable for keyread only retrieval. */
7091
2/2
✓ Branch 0 taken 6326 times.
✓ Branch 1 taken 45885480 times.
45891806 if (table_share->key_info[key].flags & HA_MULTI_VALUED_KEY) {
7092 6326 flags &= ~(HA_READ_ORDER | HA_KEYREAD_ONLY);
7093 }
7094
7095 45891806 return (flags);
7096 }
7097
7098 /** Returns the maximum number of keys.
7099 @return MAX_KEY */
7100
7101 626828 uint ha_innobase::max_supported_keys() const { return (MAX_KEY); }
7102
7103 /** Returns the maximum key length.
7104 @return maximum supported key length, in bytes */
7105
7106 1424972 uint ha_innobase::max_supported_key_length() const {
7107 /* An InnoDB page must store >= 2 keys; a secondary key record
7108 must also contain the primary key value. Therefore, if both
7109 the primary key and the secondary key are at this maximum length,
7110 it must be less than 1/4th of the free space on a page including
7111 record overhead.
7112
7113 MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072.
7114
7115 For page sizes = 16k, InnoDB historically reported 3500 bytes here,
7116 But the MySQL limit of 3072 was always used through the handler
7117 interface. */
7118
7119
3/3
✓ Branch 0 taken 3013 times.
✓ Branch 1 taken 1294 times.
✓ Branch 2 taken 1420665 times.
1424972 switch (UNIV_PAGE_SIZE) {
7120 3013 case 4096:
7121 3013 return (768);
7122 1294 case 8192:
7123 1294 return (1536);
7124 1420665 default:
7125 1420665 return (3500);
7126 }
7127 }
7128
7129 /** Determines if the primary key is clustered index.
7130 @return true */
7131
7132 12320137 bool ha_innobase::primary_key_is_clustered() const { return (true); }
7133
7134 6945530 bool create_table_info_t::normalize_table_name(char *norm_name,
7135 const char *name) {
7136 const char *name_ptr;
7137 ulint name_len;
7138 const char *db_ptr;
7139 ulint db_len;
7140 const char *ptr;
7141 ulint norm_len;
7142
7143 /* Scan name from the end */
7144
7145 6945530 ptr = strend(name) - 1;
7146
7147 /* seek to the last path separator */
7148
6/6
✓ Branch 0 taken 96448894 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 96448888 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 89503367 times.
✓ Branch 5 taken 6945521 times.
96448908 while (ptr >= name && *ptr != '\\' && *ptr != '/') {
7149 89503367 ptr--;
7150 }
7151
7152 6945541 name_ptr = ptr + 1;
7153 6945541 name_len = strlen(name_ptr);
7154
7155 /* skip any number of path separators */
7156
5/6
✓ Branch 0 taken 13891082 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13891081 times.
✓ Branch 4 taken 6945540 times.
✓ Branch 5 taken 6945541 times.
13891082 while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
7157 6945541 ptr--;
7158 }
7159
7160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6945541 times.
6945541 assert(ptr >= name);
7161
7162 /* seek to the last but one path separator or one char before
7163 the beginning of name */
7164 6945541 db_len = 0;
7165
5/6
✓ Branch 0 taken 43456027 times.
✓ Branch 1 taken 210897 times.
✓ Branch 2 taken 43456039 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36721383 times.
✓ Branch 5 taken 6734656 times.
43666924 while (ptr >= name && *ptr != '\\' && *ptr != '/') {
7166 36721383 ptr--;
7167 36721383 db_len++;
7168 }
7169
7170 6945541 db_ptr = ptr + 1;
7171
7172 6945541 norm_len = db_len + name_len + sizeof "/";
7173
7174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6945541 times.
6945541 if (norm_len >= FN_REFLEN - 1) {
7175 /* purecov: begin assert */
7176 ut_d(ut_error);
7177 ut_o(return (false));
7178 /* purecov: end */
7179 }
7180
7181 6945541 memcpy(norm_name, db_ptr, db_len);
7182
7183 6945541 norm_name[db_len] = '/';
7184
7185 /* Copy the name and null-byte. */
7186 6945541 memcpy(norm_name + db_len + 1, name_ptr, name_len + 1);
7187
7188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6945541 times.
6945541 if (lower_case_file_system) {
7189 ut_ad(lower_case_table_names != 0);
7190 innobase_casedn_str(norm_name);
7191 }
7192 6945533 return (true);
7193 }
7194
7195 #ifdef UNIV_DEBUG
7196 /*********************************************************************
7197 Test normalize_table_name(). */
7198 static void test_normalize_table_name() {
7199 char norm_name[FN_REFLEN];
7200 const char *test_data[][2] = {
7201 /* input, expected result */
7202 {"./mysqltest/t1", "mysqltest/t1"},
7203 {"./test/#sql-842b_2", "test/#sql-842b_2"},
7204 {"./test/#sql-85a3_10", "test/#sql-85a3_10"},
7205 {"./test/#sql2-842b-2", "test/#sql2-842b-2"},
7206 {"./test/bug29807", "test/bug29807"},
7207 {"./test/foo", "test/foo"},
7208 {"./test/innodb_bug52663", "test/innodb_bug52663"},
7209 {"./test/t", "test/t"},
7210 {"./test/t1", "test/t1"},
7211 {"./test/t10", "test/t10"},
7212 {"/a/b/db/table", "db/table"},
7213 {"/a/b/db///////table", "db/table"},
7214 {"/a/b////db///////table", "db/table"},
7215 {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
7216 {"db/table", "db/table"},
7217 {"ddd/t", "ddd/t"},
7218 {"d/ttt", "d/ttt"},
7219 {"d/t", "d/t"},
7220 {".\\mysqltest\\t1", "mysqltest/t1"},
7221 {".\\test\\#sql-842b_2", "test/#sql-842b_2"},
7222 {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
7223 {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
7224 {".\\test\\bug29807", "test/bug29807"},
7225 {".\\test\\foo", "test/foo"},
7226 {".\\test\\innodb_bug52663", "test/innodb_bug52663"},
7227 {".\\test\\t", "test/t"},
7228 {".\\test\\t1", "test/t1"},
7229 {".\\test\\t10", "test/t10"},
7230 {"C:\\a\\b\\db\\table", "db/table"},
7231 {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
7232 {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
7233 {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
7234 {"db\\table", "db/table"},
7235 {"ddd\\t", "ddd/t"},
7236 {"d\\ttt", "d/ttt"},
7237 {"d\\t", "d/t"},
7238 };
7239
7240 for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
7241 printf(
7242 "test_normalize_table_name():"
7243 " testing \"%s\", expected \"%s\"... ",
7244 test_data[i][0], test_data[i][1]);
7245
7246 create_table_info_t::normalize_table_name(norm_name, test_data[i][0]);
7247
7248 if (strcmp(norm_name, test_data[i][1]) == 0) {
7249 printf("ok\n");
7250 } else {
7251 printf("got \"%s\"\n", norm_name);
7252 ut_error;
7253 }
7254 }
7255 }
7256
7257 /*********************************************************************
7258 Test ut_format_name(). */
7259 static void test_ut_format_name() {
7260 char buf[NAME_LEN * 3];
7261
7262 struct {
7263 const char *name;
7264 ulint buf_size;
7265 const char *expected;
7266 } test_data[] = {
7267 {"test/t1", sizeof(buf), "`test`.`t1`"},
7268 {"test/t1", 12, "`test`.`t1`"},
7269 {"test/t1", 11, "`test`.`t1"},
7270 {"test/t1", 10, "`test`.`t"},
7271 {"test/t1", 9, "`test`.`"},
7272 {"test/t1", 8, "`test`."},
7273 {"test/t1", 7, "`test`"},
7274 {"test/t1", 6, "`test"},
7275 {"test/t1", 5, "`tes"},
7276 {"test/t1", 4, "`te"},
7277 {"test/t1", 3, "`t"},
7278 {"test/t1", 2, "`"},
7279 {"test/t1", 1, ""},
7280 {"test/t1", 0, "BUF_NOT_CHANGED"},
7281 {"table", sizeof(buf), "`table`"},
7282 {"ta'le", sizeof(buf), "`ta'le`"},
7283 {"ta\"le", sizeof(buf), "`ta\"le`"},
7284 {"ta`le", sizeof(buf), "`ta``le`"},
7285 };
7286
7287 for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
7288 memcpy(buf, "BUF_NOT_CHANGED", strlen("BUF_NOT_CHANGED") + 1);
7289
7290 char *ret;
7291
7292 ret = ut_format_name(test_data[i].name, buf, test_data[i].buf_size);
7293
7294 ut_a(ret == buf);
7295
7296 if (strcmp(buf, test_data[i].expected) == 0) {
7297 ib::info(ER_IB_MSG_550) << "ut_format_name(" << test_data[i].name
7298 << ", buf, " << test_data[i].buf_size
7299 << "),"
7300 " expected "
7301 << test_data[i].expected << ", OK";
7302 } else {
7303 ib::error(ER_IB_MSG_551)
7304 << "ut_format_name(" << test_data[i].name << ", buf, "
7305 << test_data[i].buf_size
7306 << "),"
7307 " expected "
7308 << test_data[i].expected << ", ERROR: got " << buf;
7309 ut_error;
7310 }
7311 }
7312 }
7313 #endif /* UNIV_DEBUG */
7314
7315 /** Match index columns between MySQL and InnoDB.
7316 This function checks whether the index column information
7317 is consistent between KEY info from mysql and that from innodb index.
7318 @param[in] key_info Index info from mysql
7319 @param[in] index_info Index info from InnoDB
7320 @return true if all column types match. */
7321 4424558 bool innobase_match_index_columns(const KEY *key_info,
7322 const dict_index_t *index_info) {
7323 const KEY_PART_INFO *key_part;
7324 const KEY_PART_INFO *key_end;
7325 const dict_field_t *innodb_idx_fld;
7326 const dict_field_t *innodb_idx_fld_end;
7327
7328
1/2
✓ Branch 0 taken 4424558 times.
✗ Branch 1 not taken.
4424558 DBUG_TRACE;
7329
7330 /* Check whether user defined index column count matches */
7331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4424558 times.
4424558 if (key_info->user_defined_key_parts != index_info->n_user_defined_cols) {
7332 return false;
7333 }
7334
7335 4424558 key_part = key_info->key_part;
7336 4424558 key_end = key_part + key_info->user_defined_key_parts;
7337 4424558 innodb_idx_fld = index_info->fields;
7338 4424558 innodb_idx_fld_end = index_info->fields + index_info->n_fields;
7339
7340 /* Check each index column's datatype. We do not check
7341 column name because there exists case that index
7342 column name got modified in mysql but such change does not
7343 propagate to InnoDB.
7344 One hidden assumption here is that the index column sequences
7345 are matched up between those in mysql and InnoDB. */
7346
2/2
✓ Branch 0 taken 7422099 times.
✓ Branch 1 taken 4424558 times.
11846657 for (; key_part != key_end; ++key_part) {
7347 ulint col_type;
7348 ulint is_unsigned;
7349 7422099 ulint mtype = innodb_idx_fld->col->mtype;
7350
7351 /* Need to translate to InnoDB column type before
7352 comparison. */
7353
1/2
✓ Branch 0 taken 7422099 times.
✗ Branch 1 not taken.
7422099 col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field);
7354
7355 /* Ignore InnoDB specific system columns. */
7356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7422099 times.
7422099 while (mtype == DATA_SYS) {
7357 innodb_idx_fld++;
7358
7359 if (innodb_idx_fld >= innodb_idx_fld_end) {
7360 return false;
7361 }
7362 }
7363
7364 7422099 if ((bool)innodb_idx_fld->is_ascending !=
7365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7422099 times.
7422099 !(key_part->key_part_flag & HA_REVERSE_SORT)) {
7366 /* Column Type mismatches */
7367 return false;
7368 }
7369
7370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7422099 times.
7422099 if (col_type != mtype) {
7371 /* If the col_type we get from mysql type is a geometry
7372 data type, we should check if mtype is a legacy type
7373 from 5.6, either upgraded to DATA_GEOMETRY or not.
7374 This is indeed not an accurate check, but should be
7375 safe, since DATA_BLOB would be upgraded once we create
7376 spatial index on it and we intend to use DATA_GEOMETRY
7377 for legacy GIS data types which are of var-length. */
7378 switch (col_type) {
7379 case DATA_POINT:
7380 case DATA_VAR_POINT:
7381 if (DATA_POINT_MTYPE(mtype) || mtype == DATA_GEOMETRY ||
7382 mtype == DATA_BLOB) {
7383 break;
7384 }
7385 [[fallthrough]];
7386 case DATA_GEOMETRY:
7387 if (mtype == DATA_BLOB) {
7388 break;
7389 }
7390 [[fallthrough]];
7391 default:
7392 /* Column type mismatches */
7393 return false;
7394 }
7395 }
7396
7397 7422099 innodb_idx_fld++;
7398 }
7399
7400 4424558 return true;
7401 4424558 }
7402
7403 /** Build a template for a base column for a virtual column
7404 @param[in] table MySQL TABLE
7405 @param[in] clust_index InnoDB clustered index
7406 @param[in] field field in MySQL table
7407 @param[in] col InnoDB column
7408 @param[in,out] templ template to fill
7409 @param[in] col_no field index for virtual col
7410 */
7411 115811 static void innobase_vcol_build_templ(const TABLE *table,
7412 const dict_index_t *clust_index,
7413 Field *field, const dict_col_t *col,
7414 mysql_row_templ_t *templ, ulint col_no) {
7415
2/2
✓ Branch 0 taken 61617 times.
✓ Branch 1 taken 54194 times.
115811 if (col->is_virtual()) {
7416 61617 templ->is_virtual = true;
7417 61617 templ->col_no = col_no;
7418 61617 templ->clust_rec_field_no = ULINT_UNDEFINED;
7419 61617 templ->rec_field_no = col->ind;
7420 } else {
7421 54194 templ->is_virtual = false;
7422 54194 templ->col_no = col_no;
7423 54194 templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
7424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54194 times.
54194 ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED);
7425
7426 54194 templ->rec_field_no = templ->clust_rec_field_no;
7427 }
7428
7429 115811 templ->icp_rec_field_no = ULINT_UNDEFINED;
7430
7431
2/2
✓ Branch 0 taken 62561 times.
✓ Branch 1 taken 53250 times.
115811 if (field->is_nullable()) {
7432 62561 templ->mysql_null_byte_offset = field->null_offset();
7433
7434 62561 templ->mysql_null_bit_mask = (ulint)field->null_bit;
7435 } else {
7436 53250 templ->mysql_null_bit_mask = 0;
7437 }
7438
7439 115811 templ->mysql_col_offset = static_cast<ulint>(get_field_offset(table, field));
7440 115811 templ->mysql_col_len = static_cast<ulint>(field->pack_length());
7441 /* The multi-value index indexes attribute values in a JSON doc, so its
7442 index field length could be different from the actual column data length */
7443
6/6
✓ Branch 0 taken 61617 times.
✓ Branch 1 taken 54194 times.
✓ Branch 2 taken 577 times.
✓ Branch 3 taken 61040 times.
✓ Branch 4 taken 577 times.
✓ Branch 5 taken 115234 times.
115811 if (templ->is_virtual && innobase_is_multi_value_fld(field)) {
7444 577 templ->mysql_mvidx_len = static_cast<ulint>(field->key_length());
7445 577 templ->is_multi_val = true;
7446 } else {
7447 115234 templ->mysql_mvidx_len = 0;
7448 115234 templ->is_multi_val = false;
7449 }
7450
7451 115811 templ->type = col->mtype;
7452 115811 templ->mysql_type = static_cast<ulint>(field->type());
7453
7454
2/2
✓ Branch 0 taken 50292 times.
✓ Branch 1 taken 65519 times.
115811 if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
7455 50292 templ->mysql_length_bytes = field->get_length_bytes();
7456 }
7457
7458 115811 templ->charset = dtype_get_charset_coll(col->prtype);
7459 115811 templ->mbminlen = col->get_mbminlen();
7460 115811 templ->mbmaxlen = col->get_mbmaxlen();
7461 115811 templ->is_unsigned = col->prtype & DATA_UNSIGNED;
7462 115811 templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED);
7463 115811 templ->zip_dict_data = field->zip_dict_data;
7464 115811 }
7465
7466 /** Callback used by MySQL server layer to initialize
7467 the table virtual columns' template
7468 @param[in] table MySQL TABLE
7469 @param[in,out] ib_table InnoDB table */
7470 1 void innobase_build_v_templ_callback(const TABLE *table, void *ib_table) {
7471 1 const dict_table_t *t_table = static_cast<dict_table_t *>(ib_table);
7472
7473 1 innobase_build_v_templ(table, t_table, t_table->vc_templ, nullptr, true,
7474 nullptr);
7475 1 }
7476
7477 /** Build template for the virtual columns and their base columns. This
7478 is done when the table first opened.
7479 @param[in] table MySQL TABLE
7480 @param[in] ib_table InnoDB dict_table_t
7481 @param[in,out] s_templ InnoDB template structure
7482 @param[in] add_v new virtual columns added along with
7483 add index call
7484 @param[in] locked true if dict_sys mutex is held
7485 @param[in] share_tbl_name original MySQL table name */
7486 54246 void innobase_build_v_templ(const TABLE *table, const dict_table_t *ib_table,
7487 dict_vcol_templ_t *s_templ,
7488 const dict_add_v_col_t *add_v, bool locked,
7489 const char *share_tbl_name) {
7490 54246 ulint ncol = ib_table->n_cols - DATA_N_SYS_COLS;
7491 54246 ulint n_v_col = ib_table->n_v_cols;
7492 bool marker[REC_MAX_N_FIELDS];
7493
7494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54246 times.
54246 ut_ad(ncol < REC_MAX_N_FIELDS);
7495
7496
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 54078 times.
54246 if (add_v != nullptr) {
7497 168 n_v_col += add_v->n_v_col;
7498 }
7499
7500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54246 times.
54246 ut_ad(n_v_col > 0);
7501
7502
2/2
✓ Branch 0 taken 991 times.
✓ Branch 1 taken 53255 times.
54246 if (!locked) {
7503
1/2
✓ Branch 0 taken 991 times.
✗ Branch 1 not taken.
991 dict_sys_mutex_enter();
7504 }
7505
7506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54246 times.
54246 if (s_templ->vtempl) {
7507 if (!locked) {
7508 dict_sys_mutex_exit();
7509 }
7510 return;
7511 }
7512
7513 54246 memset(marker, 0, sizeof(bool) * ncol);
7514
7515 54246 s_templ->vtempl = static_cast<mysql_row_templ_t **>(ut::zalloc_withkey(
7516 54246 UT_NEW_THIS_FILE_PSI_KEY, (ncol + n_v_col) * sizeof *s_templ->vtempl));
7517 54246 s_templ->n_col = ncol;
7518 54246 s_templ->n_v_col = n_v_col;
7519 54246 s_templ->rec_len = table->s->reclength;
7520 54246 s_templ->default_rec = static_cast<byte *>(
7521 54246 ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, table->s->reclength));
7522 54246 memcpy(s_templ->default_rec, table->s->default_values, table->s->reclength);
7523
7524 /* Mark those columns could be base columns */
7525
2/2
✓ Branch 0 taken 61436 times.
✓ Branch 1 taken 54246 times.
115682 for (ulint i = 0; i < ib_table->n_v_cols; i++) {
7526
1/2
✓ Branch 0 taken 61436 times.
✗ Branch 1 not taken.
61436 const dict_v_col_t *vcol = dict_table_get_nth_v_col(ib_table, i);
7527
7528
2/2
✓ Branch 0 taken 60364 times.
✓ Branch 1 taken 61436 times.
121800 for (ulint j = 0; j < vcol->num_base; j++) {
7529 60364 ulint col_no = vcol->base_col[j]->ind;
7530 60364 marker[col_no] = true;
7531 }
7532 }
7533
7534
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 54078 times.
54246 if (add_v) {
7535
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 168 times.
349 for (ulint i = 0; i < add_v->n_v_col; i++) {
7536 181 const dict_v_col_t *vcol = &add_v->v_col[i];
7537
7538
2/2
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 181 times.
399 for (ulint j = 0; j < vcol->num_base; j++) {
7539 218 ulint col_no = vcol->base_col[j]->ind;
7540 218 marker[col_no] = true;
7541 }
7542 }
7543 }
7544
7545 54246 ulint j = 0;
7546 54246 ulint z = 0;
7547
7548
1/2
✓ Branch 0 taken 54246 times.
✗ Branch 1 not taken.
54246 const dict_index_t *clust_index = ib_table->first_index();
7549
7550
2/2
✓ Branch 0 taken 323627 times.
✓ Branch 1 taken 54246 times.
377873 for (ulint i = 0; i < table->s->fields; i++) {
7551 323627 Field *field = table->field[i];
7552
7553 /* Build template for virtual columns */
7554
4/4
✓ Branch 0 taken 64871 times.
✓ Branch 1 taken 258756 times.
✓ Branch 2 taken 61617 times.
✓ Branch 3 taken 3254 times.
323627 if (innobase_is_v_fld(field)) {
7555 #ifdef UNIV_DEBUG
7556 const char *name;
7557
7558
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 61436 times.
61617 if (z >= ib_table->n_v_def) {
7559 181 name = add_v->v_col_name[z - ib_table->n_v_def];
7560 } else {
7561
1/2
✓ Branch 0 taken 61436 times.
✗ Branch 1 not taken.
61436 name = dict_table_get_v_col_name(ib_table, z);
7562 }
7563
7564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61617 times.
61617 ut_ad(!ut_strcmp(name, field->field_name));
7565 #endif
7566 const dict_v_col_t *vcol;
7567
7568
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 61436 times.
61617 if (z >= ib_table->n_v_def) {
7569 181 vcol = &add_v->v_col[z - ib_table->n_v_def];
7570 } else {
7571
1/2
✓ Branch 0 taken 61436 times.
✗ Branch 1 not taken.
61436 vcol = dict_table_get_nth_v_col(ib_table, z);
7572 }
7573
7574 123234 s_templ->vtempl[z + s_templ->n_col] =
7575 61617 static_cast<mysql_row_templ_t *>(ut::malloc_withkey(
7576 61617 UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j]));
7577
7578 61617 innobase_vcol_build_templ(table, clust_index, field, &vcol->m_col,
7579
1/2
✓ Branch 0 taken 61617 times.
✗ Branch 1 not taken.
61617 s_templ->vtempl[z + s_templ->n_col], z);
7580 61617 z++;
7581 61617 continue;
7582 61617 }
7583
7584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 262010 times.
262010 ut_ad(j < ncol);
7585
7586 /* Build template for base columns */
7587
2/2
✓ Branch 0 taken 54194 times.
✓ Branch 1 taken 207816 times.
262010 if (marker[j]) {
7588
1/2
✓ Branch 0 taken 54194 times.
✗ Branch 1 not taken.
54194 dict_col_t *col = ib_table->get_col(j);
7589
7590 #ifdef UNIV_DEBUG
7591
1/2
✓ Branch 0 taken 54194 times.
✗ Branch 1 not taken.
54194 const char *name = ib_table->get_col_name(j);
7592
7593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54194 times.
54194 ut_ad(!ut_strcmp(name, field->field_name));
7594 #endif
7595
7596 54194 s_templ->vtempl[j] = static_cast<mysql_row_templ_t *>(ut::malloc_withkey(
7597 54194 UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j]));
7598
7599 54194 innobase_vcol_build_templ(table, clust_index, field, col,
7600
1/2
✓ Branch 0 taken 54194 times.
✗ Branch 1 not taken.
54194 s_templ->vtempl[j], j);
7601 }
7602
7603 262010 j++;
7604 }
7605
7606
2/2
✓ Branch 0 taken 991 times.
✓ Branch 1 taken 53255 times.
54246 if (!locked) {
7607
1/2
✓ Branch 0 taken 991 times.
✗ Branch 1 not taken.
991 dict_sys_mutex_exit();
7608 }
7609
7610
1/2
✓ Branch 0 taken 54246 times.
✗ Branch 1 not taken.
54246 s_templ->db_name = table->s->db.str;
7611
1/2
✓ Branch 0 taken 54246 times.
✗ Branch 1 not taken.
54246 s_templ->tb_name = table->s->table_name.str;
7612
7613
2/2
✓ Branch 0 taken 52434 times.
✓ Branch 1 taken 1812 times.
54246 if (share_tbl_name) {
7614
1/2
✓ Branch 0 taken 52434 times.
✗ Branch 1 not taken.
52434 s_templ->share_name = share_tbl_name;
7615 }
7616 }
7617
7618 /** This function builds a translation table in INNOBASE_SHARE
7619 structure for fast index location with mysql array number from its
7620 table->key_info structure. This also provides the necessary translation
7621 between the key order in mysql key_info and InnoDB ib_table->indexes if
7622 they are not fully matched with each other.
7623 Note we do not have any mutex protecting the translation table
7624 building based on the assumption that there is no concurrent
7625 index creation/drop and DMLs that requires index lookup. All table
7626 handle will be closed before the index creation/drop.
7627 @return true if index translation table built successfully */
7628 4556680 bool innobase_build_index_translation(
7629 const TABLE *table, /*!< in: table in MySQL data
7630 dictionary */
7631 dict_table_t *ib_table, /*!< in: table in InnoDB data
7632 dictionary */
7633 INNOBASE_SHARE *share) /*!< in/out: share structure
7634 where index translation table
7635 will be constructed in. */
7636 {
7637
1/2
✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
4556680 DBUG_TRACE;
7638
7639 4556683 bool ret = true;
7640
7641
1/2
✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
4556683 dict_sys_mutex_enter();
7642
7643 4556683 ulint mysql_num_index = table->s->keys;
7644
1/2
✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
4556683 ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
7645 4556683 dict_index_t **index_mapping = share->idx_trans_tbl.index_mapping;
7646
7647 /* If there exists inconsistency between MySQL and InnoDB dictionary
7648 (metadata) information, the number of index defined in MySQL
7649 could exceed that in InnoDB, do not build index translation
7650 table in such case */
7651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4556683 times.
4556683 if (ib_num_index < mysql_num_index) {
7652 ret = false;
7653 goto func_exit;
7654 }
7655
7656 /* If index entry count is non-zero, nothing has
7657 changed since last update, directly return true */
7658
2/2
✓ Branch 0 taken 2349848 times.
✓ Branch 1 taken 2206835 times.
4556683 if (share->idx_trans_tbl.index_count) {
7659 /* Index entry count should still match mysql_num_index */
7660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2349848 times.
2349848 ut_a(share->idx_trans_tbl.index_count == mysql_num_index);
7661 2349848 goto func_exit;
7662 }
7663
7664 /* The number of index increased, rebuild the mapping table */
7665
2/2
✓ Branch 0 taken 1743389 times.
✓ Branch 1 taken 463446 times.
2206835 if (mysql_num_index > share->idx_trans_tbl.array_size) {
7666 index_mapping = reinterpret_cast<dict_index_t **>(
7667 1743389 ut::realloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, index_mapping,
7668 mysql_num_index * sizeof(*index_mapping)));
7669
7670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1743389 times.
1743389 if (index_mapping == nullptr) {
7671 /* Report an error if index_mapping continues to be
7672 NULL and mysql_num_index is a non-zero value */
7673 log_errlog(ERROR_LEVEL, ER_INNODB_TRX_XLATION_TABLE_OOM, mysql_num_index,
7674 share->idx_trans_tbl.array_size);
7675 ret = false;
7676 goto func_exit;
7677 }
7678
7679 1743389 share->idx_trans_tbl.array_size = mysql_num_index;
7680 }
7681
7682 /* For each index in the mysql key_info array, fetch its
7683 corresponding InnoDB index pointer into index_mapping
7684 array. */
7685
2/2
✓ Branch 0 taken 4392113 times.
✓ Branch 1 taken 2206835 times.
6598948 for (ulint count = 0; count < mysql_num_index; count++) {
7686 /* Fetch index pointers into index_mapping according to mysql
7687 index sequence */
7688 8784226 index_mapping[count] =
7689
1/2
✓ Branch 0 taken 4392113 times.
✗ Branch 1 not taken.
4392113 dict_table_get_index_on_name(ib_table, table->key_info[count].name);
7690
7691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4392113 times.
4392113 if (index_mapping[count] == nullptr) {
7692 log_errlog(ERROR_LEVEL, ER_INNODB_CANT_FIND_INDEX_IN_INNODB_DD,
7693 table->key_info[count].name);
7694 ret = false;
7695 goto func_exit;
7696 }
7697
7698 /* Double check fetched index has the same
7699 column info as those in mysql key_info. */
7700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4392113 times.
4392113 if (!innobase_match_index_columns(&table->key_info[count],
7701
1/2
✓ Branch 0 taken 4392113 times.
✗ Branch 1 not taken.
4392113 index_mapping[count])) {
7702 log_errlog(ERROR_LEVEL, ER_INNODB_INDEX_COLUMN_INFO_UNLIKE_MYSQLS,
7703 table->key_info[count].name);
7704 ret = false;
7705 goto func_exit;
7706 }
7707 }
7708
7709 /* Successfully built the translation table */
7710 2206835 share->idx_trans_tbl.index_count = mysql_num_index;
7711
7712 4556683 func_exit:
7713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4556683 times.
4556683 if (!ret) {
7714 /* Build translation table failed. */
7715 ut::free(index_mapping);
7716
7717 share->idx_trans_tbl.array_size = 0;
7718 share->idx_trans_tbl.index_count = 0;
7719 index_mapping = nullptr;
7720 }
7721
7722 4556683 share->idx_trans_tbl.index_mapping = index_mapping;
7723
7724
1/2
✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
4556683 dict_sys_mutex_exit();
7725
7726 4556683 return ret;
7727 4556683 }
7728
7729 /** This function uses index translation table to quickly locate the
7730 requested index structure.
7731 Note we do not have mutex protection for the index translatoin table
7732 access, it is based on the assumption that there is no concurrent
7733 translation table rebuild (fter create/drop index) and DMLs that
7734 require index lookup.
7735 @return dict_index_t structure for requested index. NULL if
7736 fail to locate the index structure. */
7737 131401507 static dict_index_t *innobase_index_lookup(
7738 INNOBASE_SHARE *share, /*!< in: share structure for index
7739 translation table. */
7740 uint keynr) /*!< in: index number for the requested
7741 index */
7742 {
7743
1/2
✓ Branch 0 taken 131401588 times.
✗ Branch 1 not taken.
131401507 if (share->idx_trans_tbl.index_mapping == nullptr ||
7744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131401661 times.
131401588 keynr >= share->idx_trans_tbl.index_count) {
7745 return (nullptr);
7746 }
7747
7748 131401661 return (share->idx_trans_tbl.index_mapping[keynr]);
7749 }
7750
7751 /** Set the autoinc column max value. This should only be called from
7752 ha_innobase::open, therefore there's no need for a covering lock. */
7753 126630 void ha_innobase::innobase_initialize_autoinc() {
7754 ulonglong auto_inc;
7755 126630 const Field *field = table->found_next_number_field;
7756
7757
1/2
✓ Branch 0 taken 126630 times.
✗ Branch 1 not taken.
126630 if (field != nullptr) {
7758 126630 auto_inc = field->get_max_int_value();
7759
7760 /* autoinc column cannot be virtual column */
7761
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 126630 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 126630 times.
126630 ut_ad(!innobase_is_v_fld(field));
7762 } else {
7763 /* We have no idea what's been passed in to us as the
7764 autoinc column. We set it to the 0, effectively disabling
7765 updates to the table. */
7766 auto_inc = 0;
7767
7768 ib::info(ER_IB_MSG_552) << "Unable to determine the AUTOINC column name";
7769 }
7770
7771
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 126536 times.
126630 if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
7772 /* If the recovery level is set so high that writes
7773 are disabled we force the AUTOINC counter to 0
7774 value effectively disabling writes to the table.
7775 Secondly, we avoid reading the table in case the read
7776 results in failure due to a corrupted table/index.
7777
7778 We will not return an error to the client, so that the
7779 tables can be dumped with minimal hassle. If an error
7780 were returned in this case, the first attempt to read
7781 the table would fail and subsequent SELECTs would succeed. */
7782 94 auto_inc = 0;
7783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126536 times.
126536 } else if (field == nullptr) {
7784 /* This is a far more serious error, best to avoid
7785 opening the table and return failure. */
7786 my_error(ER_AUTOINC_READ_FAILED, MYF(0));
7787 } else {
7788 126536 dict_index_t *index = nullptr;
7789 const char *col_name;
7790 uint64_t read_auto_inc;
7791 ulint err;
7792
7793
2/4
✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126536 times.
✗ Branch 3 not taken.
126536 update_thd(ha_thd());
7794
7795 126536 col_name = field->field_name;
7796
7797
1/2
✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
126536 read_auto_inc = dict_table_autoinc_read(m_prebuilt->table);
7798
7799
2/2
✓ Branch 0 taken 25727 times.
✓ Branch 1 taken 100809 times.
126536 if (read_auto_inc == 0) {
7800
1/2
✓ Branch 0 taken 25727 times.
✗ Branch 1 not taken.
25727 index = innobase_get_index(table->s->next_number_index);
7801
7802 /* Execute SELECT MAX(col_name) FROM TABLE;
7803 This is necessary when an imported tablespace
7804 doesn't have a correct cfg file so autoinc
7805 has not been initialized, or the table is empty. */
7806
1/2
✓ Branch 0 taken 25727 times.
✗ Branch 1 not taken.
25727 err = row_search_max_autoinc(index, col_name, &read_auto_inc);
7807
7808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25727 times.
25727 if (read_auto_inc > 0) {
7809 ib::warn(ER_IB_MSG_553)
7810 << "Reading max(auto_inc_col) = " << read_auto_inc << " for table "
7811 << index->table->name << ", because there was an IMPORT"
7812 << " without cfg file.";
7813 }
7814
7815 } else {
7816 100809 err = DB_SUCCESS;
7817 }
7818
7819
1/3
✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
126536 switch (err) {
7820 126536 case DB_SUCCESS: {
7821 ulonglong col_max_value;
7822
7823
1/2
✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
126536 col_max_value = field->get_max_int_value();
7824
7825 /* At the this stage we do not know the increment
7826 nor the offset, so use a default increment of 1. */
7827
7828
1/2
✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
126536 auto_inc = innobase_next_autoinc(read_auto_inc, 1, 1, 0, col_max_value);
7829
7830 126536 break;
7831 }
7832 case DB_RECORD_NOT_FOUND:
7833 ib::error(ER_IB_MSG_554) << "MySQL and InnoDB data dictionaries are"
7834 " out of sync. Unable to find the AUTOINC"
7835 " column "
7836 << col_name
7837 << " in the InnoDB"
7838 " table "
7839 << index->table->name
7840 << ". We set"
7841 " the next AUTOINC column value to 0, in"
7842 " effect disabling the AUTOINC next value"
7843 " generation.";
7844
7845 ib::info(ER_IB_MSG_555) << "You can either set the next AUTOINC"
7846 " value explicitly using ALTER TABLE or fix"
7847 " the data dictionary by recreating the"
7848 " table.";
7849
7850 /* This will disable the AUTOINC generation. */
7851 auto_inc = 0;
7852
7853 /* We want the open to succeed, so that the user can
7854 take corrective action. ie. reads should succeed but
7855 updates should fail. */
7856 err = DB_SUCCESS;
7857 break;
7858 default:
7859 /* row_search_max_autoinc() should only return
7860 one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
7861 ut_error;
7862 }
7863 }
7864
7865 126630 dict_table_autoinc_initialize(m_prebuilt->table, auto_inc);
7866 126630 }
7867
7868 /** Open an InnoDB table.
7869 @param[in] name table name
7870 @param[in] open_flags flags for opening table from SQL-layer.
7871 @param[in] table_def dd::Table object describing table to be opened
7872 @retval 1 if error
7873 @retval 0 if success */
7874 4556991 int ha_innobase::open(const char *name, int, uint open_flags,
7875 const dd::Table *table_def) {
7876 dict_table_t *ib_table;
7877 char norm_name[FN_REFLEN];
7878 THD *thd;
7879 4556991 bool cached = false;
7880
7881
1/2
✓ Branch 0 taken 4557001 times.
✗ Branch 1 not taken.
4556991 DBUG_TRACE;
7882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4557001 times.
4557001 assert(table_share == table->s);
7883
7884
1/2
✓ Branch 0 taken 4556999 times.
✗ Branch 1 not taken.
4557001 thd = ha_thd();
7885
7886
2/4
✓ Branch 0 taken 4556993 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556993 times.
4556999 if (!normalize_table_name(norm_name, name)) {
7887 /* purecov: begin inspected */
7888 ut_d(ut_error);
7889 ut_o(return (HA_ERR_TOO_LONG_PATH));
7890 /* purecov: end */
7891 }
7892
7893 4556993 m_user_thd = nullptr;
7894 4556993 m_share = nullptr;
7895
7896 /* Will be allocated if it is needed in ::update_row() */
7897 4556993 m_upd_buf = nullptr;
7898 4556993 m_upd_buf_size = 0;
7899
7900 /* Get pointer to a table object in InnoDB dictionary cache.
7901 For intrinsic table, get it from session private data */
7902
2/4
✓ Branch 0 taken 4557001 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556999 times.
✗ Branch 3 not taken.
4556993 ib_table = thd_to_innodb_session(thd)->lookup_table_handler(norm_name);
7903
7904
2/2
✓ Branch 0 taken 4374131 times.
✓ Branch 1 taken 182868 times.
4556999 if (ib_table == nullptr) {
7905
3/4
✓ Branch 0 taken 4284328 times.
✓ Branch 1 taken 89803 times.
✓ Branch 2 taken 4284331 times.
✗ Branch 3 not taken.
4374131 DEBUG_SYNC_C("ha_innobase_open");
7906
7907
1/2
✓ Branch 0 taken 4374135 times.
✗ Branch 1 not taken.
4374134 dict_sys_mutex_enter();
7908
1/2
✓ Branch 0 taken 4374135 times.
✗ Branch 1 not taken.
4374135 ib_table = dict_table_check_if_in_cache_low(norm_name);
7909
2/2
✓ Branch 0 taken 3491293 times.
✓ Branch 1 taken 882842 times.
4374135 if (ib_table != nullptr) {
7910
3/4
✓ Branch 0 taken 3491293 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3491291 times.
3491293 if (ib_table->is_corrupted()) {
7911 /* Optionally remove this corrupted table from cache now
7912 if no other thread is still using it. If not, the corrupted bit
7913 will keep it from being used.*/
7914
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ib_table->get_ref_count() == 0) {
7915
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_table_remove_from_cache(ib_table);
7916 }
7917 2 ib_table = nullptr;
7918 2 cached = true;
7919
2/2
✓ Branch 0 taken 6560 times.
✓ Branch 1 taken 3484731 times.
3491291 } else if (ib_table->refresh_fk) {
7920
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 ib_table->acquire_with_lock();
7921
7922
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 dict_names_t fk_tables;
7923
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 dict_sys_mutex_exit();
7924
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
7925
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 dd::cache::Dictionary_client::Auto_releaser releaser(client);
7926
7927 19680 dberr_t err = dd_table_load_fk(
7928
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 client, ib_table->name.m_name, nullptr, ib_table,
7929 6560 &table_def->table(), thd, false,
7930
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS), &fk_tables);
7931
7932
1/2
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
6560 dict_sys_mutex_enter();
7933 6560 ib_table->refresh_fk = false;
7934
7935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6560 times.
6560 if (err != DB_SUCCESS) {
7936 ib_table->release();
7937 goto reload;
7938 }
7939
7940 6560 cached = true;
7941
4/6
✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6560 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28838 times.
✓ Branch 5 taken 3455893 times.
3491291 } else if (ib_table->discard_after_ddl) {
7942 28838 reload:
7943
1/2
✓ Branch 0 taken 28838 times.
✗ Branch 1 not taken.
28838 btr_drop_ahi_for_table(ib_table);
7944
1/2
✓ Branch 0 taken 28838 times.
✗ Branch 1 not taken.
28838 dict_table_remove_from_cache(ib_table);
7945 28838 ib_table = nullptr;
7946 } else {
7947 3455893 cached = true;
7948
2/4
✓ Branch 0 taken 3455893 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3455893 times.
3455893 if (!dd_table_match(ib_table, table_def)) {
7949 dict_set_corrupted(ib_table->first_index());
7950 dict_table_remove_from_cache(ib_table);
7951 ib_table = nullptr;
7952 } else {
7953
1/2
✓ Branch 0 taken 3455893 times.
✗ Branch 1 not taken.
3455893 ib_table->acquire_with_lock();
7954 }
7955 }
7956
7957 /* If the table is in-memory, always get the latest
7958 version, in case this is open table after DDL */
7959
4/4
✓ Branch 0 taken 3462453 times.
✓ Branch 1 taken 28840 times.
✓ Branch 2 taken 3263178 times.
✓ Branch 3 taken 199275 times.
3491293 if (ib_table != nullptr && table_def != nullptr) {
7960
1/2
✓ Branch 0 taken 3263178 times.
✗ Branch 1 not taken.
3263178 ib_table->version = dd_get_version(table_def);
7961 }
7962
7963
2/2
✓ Branch 0 taken 3462453 times.
✓ Branch 1 taken 28840 times.
3491293 if (ib_table != nullptr) {
7964
1/2
✓ Branch 0 taken 3462453 times.
✗ Branch 1 not taken.
3462453 dict_table_ddl_release(ib_table);
7965 }
7966 }
7967
7968
1/2
✓ Branch 0 taken 4374135 times.
✗ Branch 1 not taken.
4374135 dict_sys_mutex_exit();
7969
7970
2/2
✓ Branch 0 taken 911680 times.
✓ Branch 1 taken 3462455 times.
4374135 if (!cached) {
7971
1/2
✓ Branch 0 taken 911680 times.
✗ Branch 1 not taken.
911680 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
7972
1/2
✓ Branch 0 taken 911680 times.
✗ Branch 1 not taken.
911680 dd::cache::Dictionary_client::Auto_releaser releaser(client);
7973
7974
1/2
✓ Branch 0 taken 911679 times.
✗ Branch 1 not taken.
911680 ib_table = dd_open_table(client, table, norm_name, table_def, thd);
7975
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 911677 times.
911679 if (!ib_table) {
7976
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 set_my_errno(ENOENT);
7977 2 return HA_ERR_NO_SUCH_TABLE;
7978 }
7979
2/2
✓ Branch 0 taken 911677 times.
✓ Branch 1 taken 2 times.
911679 }
7980 } else {
7981
1/2
✓ Branch 0 taken 182867 times.
✗ Branch 1 not taken.
182868 ib_table->acquire();
7982
2/4
✓ Branch 0 taken 182867 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 182867 times.
182867 ut_ad(ib_table->is_intrinsic());
7983 }
7984
7985
2/2
✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 2 times.
4556999 if (ib_table != nullptr) {
7986 /* Make sure table->is_dd_table is set */
7987 4556997 std::string db_str;
7988 4556997 std::string tbl_str;
7989
2/4
✓ Branch 0 taken 4556997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556997 times.
✗ Branch 3 not taken.
4556997 dict_name::get_table(ib_table->name.m_name, db_str, tbl_str);
7990
7991 4556997 ib_table->is_dd_table =
7992
4/8
✓ Branch 0 taken 4556997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556997 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4556997 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4556997 times.
✗ Branch 7 not taken.
4556997 dd::get_dictionary()->is_dd_table_name(db_str.c_str(), tbl_str.c_str());
7993 4556996 }
7994
7995 /* m_share might hold pointers to dict table indexes without any pin.
7996 We must always allocate m_share after opening the dict_table_t object
7997 and free it before de-allocating dict_table_t to avoid race. */
7998
2/2
✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 2 times.
4556999 if (ib_table != nullptr) {
7999
1/2
✓ Branch 0 taken 4556997 times.
✗ Branch 1 not taken.
4556997 m_share = get_share(name);
8000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4556997 times.
4556997 if (m_share == nullptr) {
8001 dict_table_close(ib_table, false, false);
8002 return HA_ERR_SE_OUT_OF_MEMORY;
8003 }
8004
8005
3/10
✗ Branch 0 not taken.
✓ Branch 1 taken 4556997 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4556997 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4556997 times.
4556997 if (UNIV_UNLIKELY(m_share->ib_table && m_share->ib_table->is_corrupt &&
8006 srv_pass_corrupt_table <= 1)) {
8007 free_share_and_nullify(&m_share);
8008 dict_table_close(ib_table, false, false);
8009 return HA_ERR_CRASHED_ON_USAGE;
8010 }
8011 }
8012
8013
3/4
✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556998 times.
9113995 if (ib_table != nullptr &&
8014
2/2
✓ Branch 0 taken 4555697 times.
✓ Branch 1 taken 1300 times.
4556997 ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) &&
8015
4/6
✓ Branch 0 taken 4555697 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4555698 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1300 times.
✓ Branch 5 taken 4555697 times.
9112694 table->s->fields != dict_table_get_n_tot_u_cols(ib_table)) ||
8016 4556998 (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) &&
8017
3/4
✓ Branch 0 taken 1300 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1299 times.
1300 (table->s->fields != dict_table_get_n_tot_u_cols(ib_table) - 1)))) {
8018 ib::warn(ER_IB_MSG_556)
8019 << "Table " << norm_name << " contains " << ib_table->get_n_user_cols()
8020 << " user"
8021 " defined columns in InnoDB, but "
8022 << table->s->fields
8023 << " columns in MySQL. Please check"
8024 " INFORMATION_SCHEMA.INNODB_COLUMNS and " REFMAN
8025 "innodb-troubleshooting.html for how to resolve the"
8026 " issue.";
8027
8028 /* Mark this table as corrupted, so the drop table
8029 or force recovery can still use it, but not others. */
8030 ib_table->first_index()->type |= DICT_CORRUPT;
8031 free_share_and_nullify(&m_share);
8032 dict_table_close(ib_table, false, false);
8033 ib_table = nullptr;
8034 }
8035
8036
5/10
✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556997 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4556998 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4556998 times.
4556998 if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt &&
8037 srv_pass_corrupt_table <= 1)) {
8038 free_share_and_nullify(&m_share);
8039 dict_table_close(ib_table, false, false);
8040 return HA_ERR_CRASHED_ON_USAGE;
8041 }
8042
8043 9113988 FilSpace space;
8044
4/6
✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4556996 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4556999 times.
✗ Branch 5 not taken.
4556998 if (ib_table) space = fil_space_acquire_silent(ib_table->space);
8045
8046 /* For encrypted table, check if the encryption info in data
8047 file can't be retrieved properly, mark it as corrupted. */
8048 9113995 if (ib_table != nullptr &&
8049
3/4
✓ Branch 0 taken 4556996 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4541191 times.
✓ Branch 3 taken 15805 times.
4556997 (dd_is_table_in_encrypted_tablespace(ib_table) ||
8050
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4541191 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4541191 (ib_table->keyring_encryption_info.page0_has_crypt_data &&
8051 ib_table->keyring_encryption_info.is_encryption_in_progress())) &&
8052
8/8
✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 309 times.
✓ Branch 3 taken 15491 times.
✓ Branch 4 taken 269 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 269 times.
✓ Branch 7 taken 4556730 times.
9113996 ib_table->ibd_file_missing && !dict_table_is_discarded(ib_table)) {
8053 /* Mark this table as corrupted, so the drop table
8054 or force recovery can still use it, but not others. */
8055 269 FilSpace space;
8056 269 int error = 0;
8057
3/6
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
269 if (ib_table) space = fil_space_acquire_silent(ib_table->space);
8058
2/4
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
538 if (space() == NULL &&
8059
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 (ib_table->keyring_encryption_info.keyring_encryption_key_is_missing ||
8060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
269 ib_table->keyring_encryption_info.page0_has_crypt_data)) {
8061 /* Proper error message has been already printed by
8062 * Datafile::validate_first_page, thus we do not print anything here */
8063 error = HA_ERR_ENCRYPTION_KEY_MISSING;
8064 } else {
8065
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
8066 269 error = HA_ERR_TABLE_CORRUPT;
8067 }
8068
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 dict_table_close(ib_table, false, false);
8069 269 ib_table = nullptr;
8070
8071
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 free_share_and_nullify(&m_share);
8072 269 return error;
8073 269 }
8074
8075
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4556728 times.
4556730 if (nullptr == ib_table) {
8076
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 ib::warn(ER_IB_MSG_557)
8077
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 << "Cannot open table " << norm_name << TROUBLESHOOTING_MSG;
8078
8079
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 set_my_errno(ENOENT);
8080
8081 2 return HA_ERR_NO_SUCH_TABLE;
8082 }
8083
8084
1/2
✓ Branch 0 taken 4556728 times.
✗ Branch 1 not taken.
4556728 innobase_copy_frm_flags_from_table_share(ib_table, table->s);
8085
8086
1/2
✓ Branch 0 taken 4556725 times.
✗ Branch 1 not taken.
4556728 dict_stats_init(ib_table);
8087
8088 4556725 MONITOR_INC(MONITOR_TABLE_OPEN);
8089
8090 bool no_tablespace;
8091
8092
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 4556641 times.
4556726 if (dict_table_is_discarded(ib_table)) {
8093 /* If the op is an IMPORT, open the space without this warning. */
8094
3/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 27 times.
85 if (thd_tablespace_op(thd) != Alter_info::ALTER_IMPORT_TABLESPACE) {
8095 58 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED,
8096
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 table->s->table_name.str);
8097 }
8098
8099 /* Allow an open because a proper DISCARD should have set
8100 all the flags and index root page numbers to FIL_NULL that
8101 should prevent any DML from running but it should allow DDL
8102 operations. */
8103 85 no_tablespace = false;
8104
8105
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4556593 times.
4556641 } else if (ib_table->ibd_file_missing) {
8106
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_MISSING, norm_name);
8107
8108 /* This means we have no idea what happened to the tablespace
8109 file, best to play it safe. */
8110
8111 48 no_tablespace = true;
8112 } else {
8113 4556593 no_tablespace = false;
8114 }
8115
8116
7/8
✓ Branch 0 taken 4556726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556528 times.
✓ Branch 3 taken 198 times.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 4556481 times.
✓ Branch 6 taken 47 times.
✓ Branch 7 taken 4556679 times.
4556726 if (!thd_tablespace_op(thd) && no_tablespace) {
8117
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 free_share_and_nullify(&m_share);
8118
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 set_my_errno(ENOENT);
8119
8120
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 dict_table_close(ib_table, false, false);
8121
8122 47 return HA_ERR_TABLESPACE_MISSING;
8123 }
8124
8125
1/2
✓ Branch 0 taken 4556677 times.
✗ Branch 1 not taken.
4556679 m_prebuilt = row_create_prebuilt(ib_table, table->s->reclength);
8126
8127 4556677 m_prebuilt->default_rec = table->s->default_values;
8128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4556677 times.
4556677 ut_ad(m_prebuilt->default_rec);
8129
8130 4556677 m_prebuilt->m_mysql_table = table;
8131 4556677 m_prebuilt->m_mysql_handler = this;
8132
8133
3/4
✓ Branch 0 taken 4556677 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182867 times.
✓ Branch 3 taken 4373810 times.
4556677 if (ib_table->is_intrinsic()) {
8134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182867 times.
182867 ut_ad(open_flags & HA_OPEN_INTERNAL_TABLE);
8135
8136
1/2
✓ Branch 0 taken 182867 times.
✗ Branch 1 not taken.
182867 m_prebuilt->m_temp_read_shared = table_share->ref_count() >= 2;
8137
8138
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 182531 times.
182867 if (m_prebuilt->m_temp_read_shared) {
8139
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 224 times.
336 if (ib_table->temp_prebuilt == nullptr) {
8140 112 ib_table->temp_prebuilt =
8141
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 ut::new_withkey<temp_prebuilt_vec>(UT_NEW_THIS_FILE_PSI_KEY);
8142 }
8143
8144
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 ib_table->temp_prebuilt->push_back(m_prebuilt);
8145 }
8146 182867 m_prebuilt->m_temp_tree_modified = false;
8147 }
8148
8149 4556677 key_used_on_scan = table_share->primary_key;
8150
8151
2/2
✓ Branch 0 taken 53155 times.
✓ Branch 1 taken 4503522 times.
4556677 if (ib_table->n_v_cols) {
8152
1/2
✓ Branch 0 taken 53155 times.
✗ Branch 1 not taken.
53155 dict_sys_mutex_enter();
8153
2/2
✓ Branch 0 taken 27960 times.
✓ Branch 1 taken 25195 times.
53155 if (ib_table->vc_templ == nullptr) {
8154 27960 ib_table->vc_templ =
8155
1/2
✓ Branch 0 taken 27960 times.
✗ Branch 1 not taken.
27960 ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY);
8156 27960 ib_table->vc_templ->vtempl = nullptr;
8157
2/2
✓ Branch 0 taken 24092 times.
✓ Branch 1 taken 1103 times.
25195 } else if (ib_table->get_ref_count() == 1) {
8158 /* Clean and refresh the template if no one else
8159 get hold on it */
8160
1/2
✓ Branch 0 taken 24092 times.
✗ Branch 1 not taken.
24092 dict_free_vc_templ(ib_table->vc_templ);
8161 24092 ib_table->vc_templ->vtempl = nullptr;
8162 }
8163
8164
2/2
✓ Branch 0 taken 52052 times.
✓ Branch 1 taken 1103 times.
53155 if (ib_table->vc_templ->vtempl == nullptr) {
8165 52052 innobase_build_v_templ(table, ib_table, ib_table->vc_templ, nullptr, true,
8166
1/2
✓ Branch 0 taken 52052 times.
✗ Branch 1 not taken.
52052 m_share->table_name);
8167 }
8168
8169
1/2
✓ Branch 0 taken 53155 times.
✗ Branch 1 not taken.
53155 dict_sys_mutex_exit();
8170 }
8171
8172
2/4
✓ Branch 0 taken 4556678 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556678 times.
4556677 if (!innobase_build_index_translation(table, ib_table, m_share)) {
8173 log_errlog(ERROR_LEVEL, ER_INNODB_CANT_BUILD_INDEX_XLATION_TABLE_FOR, name);
8174 }
8175
8176 /* Allocate a buffer for a 'row reference'. A row reference is
8177 a string of bytes of length ref_length which uniquely specifies
8178 a row in our table. Note that MySQL may also compare two row
8179 references for equality by doing a simple memcmp on the strings
8180 of length ref_length! */
8181
8182
3/4
✓ Branch 0 taken 4556679 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3867636 times.
✓ Branch 3 taken 689043 times.
4556678 if (!row_table_got_default_clust_index(ib_table)) {
8183 3867636 m_prebuilt->clust_index_was_generated = false;
8184
8185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3867636 times.
3867636 if (table_share->is_missing_primary_key()) {
8186 log_errlog(ERROR_LEVEL, ER_INNODB_PK_NOT_IN_MYSQL, name);
8187
8188 /* This mismatch could cause further problems
8189 if not attended, bring this to the user's attention
8190 by printing a warning in addition to log a message
8191 in the errorlog */
8192 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX,
8193 "InnoDB: Table %s has a"
8194 " primary key in InnoDB data"
8195 " dictionary, but not in"
8196 " MySQL!",
8197 name);
8198
8199 /* If table_share->is_missing_primary_key(),
8200 the table_share->primary_key
8201 value could be out of bound if continue to index
8202 into key_info[] array. Find InnoDB primary index,
8203 and assign its key_length to ref_length.
8204 In addition, since MySQL indexes are sorted starting
8205 with primary index, unique index etc., initialize
8206 ref_length to the first index key length in
8207 case we fail to find InnoDB cluster index.
8208
8209 Please note, this will not resolve the primary
8210 index mismatch problem, other side effects are
8211 possible if users continue to use the table.
8212 However, we allow this table to be opened so
8213 that user can adopt necessary measures for the
8214 mismatch while still being accessible to the table
8215 date. */
8216 if (!table->key_info) {
8217 ut_ad(!table->s->keys);
8218 ref_length = 0;
8219 } else {
8220 ref_length = table->key_info[0].key_length;
8221 }
8222
8223 /* Find corresponding cluster index
8224 key length in MySQL's key_info[] array */
8225 for (uint i = 0; i < table->s->keys; i++) {
8226 dict_index_t *index;
8227 index = innobase_get_index(i);
8228 if (index->is_clustered()) {
8229 ref_length = table->key_info[i].key_length;
8230 }
8231 }
8232 } else {
8233 /* MySQL allocates the buffer for ref.
8234 key_info->key_length includes space for all key
8235 columns + one byte for each column that may be
8236 NULL. ref_length must be as exact as possible to
8237 save space, because all row reference buffers are
8238 allocated based on ref_length. */
8239
8240 3867636 ref_length = table->key_info[table_share->primary_key].key_length;
8241 }
8242 } else {
8243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 689043 times.
689043 if (!table_share->is_missing_primary_key()) {
8244 log_errlog(ERROR_LEVEL, ER_INNODB_PK_ONLY_IN_MYSQL, name);
8245
8246 /* This mismatch could cause further problems
8247 if not attended, bring this to the user attention
8248 by printing a warning in addition to log a message
8249 in the errorlog */
8250 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX,
8251 "InnoDB: Table %s has no"
8252 " primary key in InnoDB data"
8253 " dictionary, but has one in"
8254 " MySQL!",
8255 name);
8256 }
8257
8258 689043 m_prebuilt->clust_index_was_generated = true;
8259
8260 689043 ref_length = DATA_ROW_ID_LEN;
8261
8262 /* If we automatically created the clustered index, then
8263 MySQL does not know about it, and MySQL must NOT be aware
8264 of the index used on scan, to make it avoid checking if we
8265 update the column of the index. That is why we assert below
8266 that key_used_on_scan is the undefined value MAX_KEY.
8267 The column is the row id in the automatical generation case,
8268 and it will never be updated anyway. */
8269
8270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 689043 times.
689043 if (key_used_on_scan != MAX_KEY) {
8271 log_errlog(WARNING_LEVEL, ER_INNODB_CLUSTERED_INDEX_PRIVATE, name,
8272 (ulong)key_used_on_scan);
8273 }
8274 }
8275
8276 /* Index block size in InnoDB: used by MySQL in query optimization */
8277 4556679 stats.block_size = UNIV_PAGE_SIZE;
8278
8279 /* Only if the table has an AUTOINC column. */
8280
4/4
✓ Branch 0 taken 4556678 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4556592 times.
✓ Branch 3 taken 86 times.
4556679 if (m_prebuilt->table != nullptr && !m_prebuilt->table->ibd_file_missing &&
8281
2/2
✓ Branch 0 taken 1718668 times.
✓ Branch 1 taken 2837924 times.
4556592 table->found_next_number_field != NULL) {
8282 1718668 dict_table_t *ib_table = m_prebuilt->table;
8283
8284
1/2
✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
1718668 dict_table_autoinc_lock(ib_table);
8285
8286
1/2
✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
1718668 uint64_t autoinc = dict_table_autoinc_read(ib_table);
8287 1718668 uint64_t autoinc_persisted = 0;
8288
8289
1/2
✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
1718668 mutex_enter(ib_table->autoinc_persisted_mutex);
8290 1718668 autoinc_persisted = ib_table->autoinc_persisted;
8291
1/2
✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
1718668 mutex_exit(ib_table->autoinc_persisted_mutex);
8292
8293 /* Since a table can already be "open" in InnoDB's internal
8294 data dictionary, we only init the autoinc counter once, the
8295 first time the table is loaded. We can safely reuse the
8296 autoinc value from a previous MySQL open. */
8297
4/4
✓ Branch 0 taken 1692901 times.
✓ Branch 1 taken 25767 times.
✓ Branch 2 taken 100863 times.
✓ Branch 3 taken 1592038 times.
1718668 if (autoinc == 0 || autoinc == autoinc_persisted) {
8298 /* If autoinc is 0, it means the counter was never
8299 used or imported from a tablespace without .cfg file.
8300 We have to search the index to get proper counter.
8301 If only the second condition is true, it means it's
8302 the first time open for the table, we just want to
8303 calculate the next counter */
8304
1/2
✓ Branch 0 taken 126630 times.
✗ Branch 1 not taken.
126630 innobase_initialize_autoinc();
8305 }
8306
8307
1/2
✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
1718668 dict_table_autoinc_set_col_pos(
8308 1718668 ib_table, table->found_next_number_field->field_index());
8309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1718668 times.
1718668 ut_ad(dict_table_has_autoinc_col(ib_table));
8310
8311
1/2
✓ Branch 0 taken 1718667 times.
✗ Branch 1 not taken.
1718668 dict_table_autoinc_unlock(ib_table);
8312 }
8313
8314 /* Set plugin parser for fulltext index */
8315
2/2
✓ Branch 0 taken 11595537 times.
✓ Branch 1 taken 4556679 times.
16152216 for (uint i = 0; i < table->s->keys; i++) {
8316
2/2
✓ Branch 0 taken 1255 times.
✓ Branch 1 taken 11594282 times.
11595537 if (table->key_info[i].flags & HA_USES_PARSER) {
8317
1/2
✓ Branch 0 taken 1255 times.
✗ Branch 1 not taken.
1255 dict_index_t *index = innobase_get_index(i);
8318 1255 plugin_ref parser = table->key_info[i].parser;
8319
8320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1255 times.
1255 ut_ad(index->type & DICT_FTS);
8321 1255 index->parser =
8322 1255 static_cast<st_mysql_ftparser *>(plugin_decl(parser)->info);
8323
8324 1255 index->is_ngram = strncmp(plugin_name(parser)->str, FTS_NGRAM_PARSER_NAME,
8325 1255 plugin_name(parser)->length) == 0;
8326
8327
3/4
✓ Branch 0 taken 1256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1252 times.
1255 DBUG_EXECUTE_IF("fts_instrument_use_default_parser",
8328 index->parser = &fts_default_parser;);
8329 }
8330 }
8331
8332
1/2
✓ Branch 0 taken 4556677 times.
✗ Branch 1 not taken.
4556679 info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
8333
8334 dberr_t err =
8335
1/2
✓ Branch 0 taken 4556675 times.
✗ Branch 1 not taken.
4556677 dict_set_compression(m_prebuilt->table, table->s->compress.str, false);
8336
8337
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4116304 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 440370 times.
4556675 switch (err) {
8338 1 case DB_NOT_FOUND:
8339 case DB_UNSUPPORTED:
8340 /* We will do another check before the create
8341 table and push the error to the client there. */
8342 1 break;
8343
8344 4116304 case DB_IO_NO_PUNCH_HOLE_TABLESPACE:
8345 /* We did the check in the 'if' above. */
8346
8347 case DB_IO_NO_PUNCH_HOLE_FS:
8348 /* During open we can't check whether the FS supports
8349 punch hole or not, at least on Linux. */
8350 4116304 break;
8351
8352 default:
8353 ut_error;
8354
8355 440370 case DB_SUCCESS:
8356 440370 break;
8357 }
8358
8359 #ifdef UNIV_DEBUG
8360 fts_aux_table_t aux_table;
8361
8362
2/4
✓ Branch 0 taken 4556671 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556671 times.
4556675 if (fts_is_aux_table_name(&aux_table, norm_name, strlen(norm_name))) {
8363 ut_ad(m_prebuilt->table->is_fts_aux());
8364 }
8365 #endif /* UNIV_DEBUG */
8366
8367
2/4
✓ Branch 0 taken 4556675 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556675 times.
4556671 if (m_prebuilt->table->is_fts_aux()) {
8368 dict_table_close(m_prebuilt->table, false, false);
8369 }
8370
8371 4556672 return 0;
8372 4556998 }
8373
8374 319350 handler *ha_innobase::clone(const char *name, /*!< in: table name */
8375 MEM_ROOT *mem_root) /*!< in: memory context */
8376 {
8377
1/2
✓ Branch 0 taken 319350 times.
✗ Branch 1 not taken.
319350 DBUG_TRACE;
8378
8379 ha_innobase *new_handler =
8380
3/4
✓ Branch 0 taken 319350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 319349 times.
✓ Branch 3 taken 1 times.
319350 dynamic_cast<ha_innobase *>(handler::clone(name, mem_root));
8381
8382
2/2
✓ Branch 0 taken 319349 times.
✓ Branch 1 taken 1 times.
319350 if (new_handler != nullptr) {
8383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 319349 times.
319349 assert(new_handler->m_prebuilt != nullptr);
8384
8385 319349 new_handler->m_prebuilt->select_lock_type = m_prebuilt->select_lock_type;
8386 }
8387
8388 319350 return new_handler;
8389 319350 }
8390
8391 2175539 uint ha_innobase::max_supported_key_part_length(
8392 HA_CREATE_INFO *create_info) const {
8393 /* A table format specific index column length check will be performed
8394 at ha_innobase::add_index() and row_create_index_for_mysql() */
8395
2/2
✓ Branch 0 taken 5973 times.
✓ Branch 1 taken 2169566 times.
2175539 switch (create_info->row_type) {
8396 5973 case ROW_TYPE_REDUNDANT:
8397 case ROW_TYPE_COMPACT:
8398 5973 return (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1);
8399 break;
8400 2169566 default:
8401 2169566 return (REC_VERSION_56_MAX_INDEX_COL_LEN);
8402 }
8403 }
8404
8405 /** Closes a handle to an InnoDB table.
8406 @return 0 */
8407
8408 4433751 int ha_innobase::close() {
8409
1/2
✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
4433751 DBUG_TRACE;
8410
8411
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 4433416 times.
4433752 if (m_prebuilt->m_temp_read_shared) {
8412 336 temp_prebuilt_vec *vec = m_prebuilt->table->temp_prebuilt;
8413
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
336 ut_ad(m_prebuilt->table->is_intrinsic());
8414
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
336 vec->erase(std::remove(vec->begin(), vec->end(), m_prebuilt), vec->end());
8415 }
8416
8417
1/2
✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
4433752 free_share_and_nullify(&m_share);
8418
8419
1/2
✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
4433752 row_prebuilt_free(m_prebuilt, false);
8420
8421
2/2
✓ Branch 0 taken 228162 times.
✓ Branch 1 taken 4205590 times.
4433752 if (m_upd_buf != nullptr) {
8422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228162 times.
228162 ut_ad(m_upd_buf_size != 0);
8423
1/2
✓ Branch 0 taken 228162 times.
✗ Branch 1 not taken.
228162 my_free(m_upd_buf);
8424 228162 m_upd_buf = nullptr;
8425 228162 m_upd_buf_size = 0;
8426 }
8427
8428 4433752 MONITOR_INC(MONITOR_TABLE_CLOSE);
8429
8430 /* Tell InnoDB server that there might be work for
8431 utility threads: */
8432
8433
1/2
✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
4433752 srv_active_wake_master_thread();
8434
8435 4433752 return 0;
8436 4433752 }
8437
8438 /* The following accessor functions should really be inside MySQL code! */
8439
8440 /** Gets field offset for a field in a table.
8441 @param[in] table MySQL table object
8442 @param[in] field MySQL field object
8443 @return offset */
8444 2289559526 static inline uint get_field_offset(const TABLE *table, const Field *field) {
8445 2289559526 return field->offset(table->record[0]);
8446 }
8447
8448 /** Compare two character string according to their charset.
8449 @param[in] cs Character set
8450 @param[in] p1 Key
8451 @param[in] p2 Node */
8452 279105551 extern int innobase_fts_text_cmp(const void *cs, const void *p1,
8453 const void *p2) {
8454 279105551 const CHARSET_INFO *charset = (const CHARSET_INFO *)cs;
8455 279105551 const fts_string_t *s1 = (const fts_string_t *)p1;
8456 279105551 const fts_string_t *s2 = (const fts_string_t *)p2;
8457
8458 558221584 return (ha_compare_text(charset, s1->f_str, static_cast<uint>(s1->f_len),
8459 279105551 s2->f_str, static_cast<uint>(s2->f_len), false));
8460 }
8461
8462 /** Compare two FTS character strings case insensitively according to their
8463 charset. This assumes that s1 is already in lower case.
8464 @param[in] cs character set
8465 @param[in] s1 key
8466 @param[in] s2 node
8467 @return 0 if the two strings are equal */
8468 1132 int innobase_fts_nocase_compare(const CHARSET_INFO *cs, const fts_string_t *s1,
8469 const fts_string_t *s2) {
8470 ulint newlen;
8471
8472
2/2
✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 103 times.
1132 if (!my_binary_compare(cs)) {
8473 1029 my_casedn_str(cs, (char *)s2->f_str);
8474 }
8475
8476 1132 newlen = strlen((const char *)s2->f_str);
8477
8478 2264 return (ha_compare_text(cs, s1->f_str, static_cast<uint>(s1->f_len),
8479 1132 s2->f_str, static_cast<uint>(newlen), false));
8480 }
8481
8482 #endif /* UNIV_HOTBACKUP */
8483
8484 /** Compare two character strings case insensitively according to their
8485 charset.
8486 @param[in] cs character set
8487 @param[in] s1 string 1
8488 @param[in] s2 string 2
8489 @return 0 if the two strings are equal */
8490 int innobase_nocase_compare(const void *cs, const char *s1, const char *s2) {
8491 const CHARSET_INFO *charset = static_cast<const CHARSET_INFO *>(cs);
8492 const uchar *str1 = reinterpret_cast<const uchar *>(s1);
8493 const uchar *str2 = reinterpret_cast<const uchar *>(s2);
8494 uint len1 = static_cast<uint>(strlen(s1));
8495 uint len2 = static_cast<uint>(strlen(s2));
8496
8497 /* This function returns zero if the two strings are equal. */
8498 return (ha_compare_text(charset, str1, len1, str2, len2, false));
8499 }
8500
8501 #ifndef UNIV_HOTBACKUP
8502
8503 4386331 ulint innobase_strnxfrm(const CHARSET_INFO *cs, const uchar *str,
8504 const ulint len) {
8505 uchar mystr[2];
8506 ulint value;
8507
8508
2/4
✓ Branch 0 taken 4386487 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4386490 times.
4386331 if (!str || len == 0) {
8509 return (0);
8510 }
8511
8512
1/2
✓ Branch 0 taken 4386073 times.
✗ Branch 1 not taken.
4386490 my_strnxfrm(cs, (uchar *)mystr, 2, str, len);
8513
8514 4386073 value = mach_read_from_2(mystr);
8515
8516
2/2
✓ Branch 0 taken 4374355 times.
✓ Branch 1 taken 11442 times.
4385797 if (value > 255) {
8517 4374355 value = value / 256;
8518 }
8519
8520 4385797 return (value);
8521 }
8522
8523 /** Compare two character string according to their charset.
8524 @param[in] cs Character set
8525 @param[in] p1 Key
8526 @param[in] p2 Node */
8527 549 extern int innobase_fts_text_cmp_prefix(const void *cs, const void *p1,
8528 const void *p2) {
8529 549 const CHARSET_INFO *charset = (const CHARSET_INFO *)cs;
8530 549 const fts_string_t *s1 = (const fts_string_t *)p1;
8531 549 const fts_string_t *s2 = (const fts_string_t *)p2;
8532 int result;
8533
8534 1098 result = ha_compare_text(charset, s2->f_str, static_cast<uint>(s2->f_len),
8535 549 s1->f_str, static_cast<uint>(s1->f_len), true);
8536
8537 /* We switched s1, s2 position in ha_compare_text. So we need
8538 to negate the result */
8539 549 return (-result);
8540 }
8541
8542 /** Makes all characters in a string lower case.
8543 @param[in] cs Character set
8544 @param[in] src String to put in lower case
8545 @param[in] src_len Input string length
8546 @param[in] dst Buffer for result string
8547 @param[in] dst_len Buffer size */
8548 16547990 extern size_t innobase_fts_casedn_str(CHARSET_INFO *cs, char *src,
8549 size_t src_len, char *dst,
8550 size_t dst_len) {
8551
2/2
✓ Branch 0 taken 16546669 times.
✓ Branch 1 taken 1321 times.
16547990 if (cs->casedn_multiply == 1) {
8552 16546669 memcpy(dst, src, src_len);
8553 16546669 dst[src_len] = 0;
8554 16546669 my_casedn_str(cs, dst);
8555
8556 16547155 return (strlen(dst));
8557 } else {
8558 1364 return (cs->cset->casedn(cs, src, src_len, dst, dst_len));
8559 }
8560 }
8561
8562 /** Get the next token from the given string and store it in *token.
8563 It is mostly copied from MyISAM's doc parsing function ft_simple_get_word()
8564 @return length of string processed */
8565 16892267 ulint innobase_mysql_fts_get_token(
8566 CHARSET_INFO *cs, /*!< in: Character set */
8567 const byte *start, /*!< in: start of text */
8568 const byte *end, /*!< in: one character past end of
8569 text */
8570 bool extra_word_chars, /*!< in: whether consider all non-whitespace
8571 characters to be word characters */
8572 fts_string_t *token) /*!< out: token's text */
8573 {
8574 int mbl;
8575 16892267 const uchar *doc = start;
8576
8577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16891654 times.
16892267 ut_a(cs);
8578
8579 16891654 token->f_n_char = token->f_len = 0;
8580 16891654 token->f_str = nullptr;
8581
8582 for (;;) {
8583
2/2
✓ Branch 0 taken 10270 times.
✓ Branch 1 taken 37231573 times.
37241843 if (doc >= end) {
8584 10270 return (doc - start);
8585 }
8586
8587 int ctype;
8588
8589
1/2
✓ Branch 0 taken 37240105 times.
✗ Branch 1 not taken.
37231573 mbl = cs->cset->ctype(cs, &ctype, doc, (const uchar *)end);
8590
8591
2/2
✓ Branch 0 taken 16891008 times.
✓ Branch 1 taken 20350189 times.
37240105 if (true_word_char(ctype, extra_word_chars, *doc)) {
8592 16891008 break;
8593 }
8594
8595
2/4
✓ Branch 0 taken 20360577 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
20350189 doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1);
8596 20350189 }
8597
8598 16891008 ulint length = 0;
8599
8600 16891008 token->f_str = const_cast<byte *>(doc);
8601
8602
2/2
✓ Branch 0 taken 164453290 times.
✓ Branch 1 taken 1722335 times.
166175625 while (doc < end) {
8603 int ctype;
8604
8605
1/2
✓ Branch 0 taken 164461796 times.
✗ Branch 1 not taken.
164453290 mbl = cs->cset->ctype(cs, &ctype, (uchar *)doc, (uchar *)end);
8606
2/2
✓ Branch 0 taken 15175709 times.
✓ Branch 1 taken 149284617 times.
164461796 if (!true_word_char(ctype, extra_word_chars, *doc)) {
8607 15175709 break;
8608 }
8609
8610 149284617 ++length;
8611
8612
1/4
✓ Branch 0 taken 149300219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
149284617 doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1);
8613 }
8614
8615 16898044 token->f_len = (uint)(doc - token->f_str);
8616 16898044 token->f_n_char = length;
8617
8618 16898044 return (doc - start);
8619 }
8620
8621 /** Converts a MySQL type to an InnoDB type. Note that this function returns
8622 the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
8623 VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'.
8624 @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'; at least
8625 ENUM and SET, and unsigned integer types are 'unsigned types'
8626 @param[in] f MySQL Field
8627 @return DATA_BINARY, DATA_VARCHAR, ... */
8628 23667486 ulint get_innobase_type_from_mysql_type(ulint *unsigned_flag, const void *f) {
8629 23667486 const class Field *field = reinterpret_cast<const class Field *>(f);
8630
8631 /* The following asserts try to check that the MySQL type code fits in
8632 8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
8633 the type */
8634
8635 assert((ulint)MYSQL_TYPE_STRING < 256);
8636 assert((ulint)MYSQL_TYPE_VAR_STRING < 256);
8637 assert((ulint)MYSQL_TYPE_DOUBLE < 256);
8638 assert((ulint)MYSQL_TYPE_FLOAT < 256);
8639 assert((ulint)MYSQL_TYPE_DECIMAL < 256);
8640
8641
2/2
✓ Branch 0 taken 8445352 times.
✓ Branch 1 taken 15222133 times.
23667486 if (field->is_flag_set(UNSIGNED_FLAG)) {
8642 8445352 *unsigned_flag = DATA_UNSIGNED;
8643 } else {
8644 15222133 *unsigned_flag = 0;
8645 }
8646
8647
4/4
✓ Branch 0 taken 21870167 times.
✓ Branch 1 taken 1797320 times.
✓ Branch 2 taken 1901222 times.
✓ Branch 3 taken 21766265 times.
45537652 if (field->real_type() == MYSQL_TYPE_ENUM ||
8648
2/2
✓ Branch 0 taken 103902 times.
✓ Branch 1 taken 21766265 times.
21870167 field->real_type() == MYSQL_TYPE_SET) {
8649 /* MySQL has field->type() a string type for these, but the
8650 data is actually internally stored as an unsigned integer
8651 code! */
8652
8653 1901222 *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
8654 flag set to zero, even though
8655 internally this is an unsigned
8656 integer type */
8657 1901222 return (DATA_INT);
8658 }
8659
8660
9/12
✓ Branch 0 taken 6454878 times.
✓ Branch 1 taken 1905760 times.
✓ Branch 2 taken 19926 times.
✓ Branch 3 taken 10639066 times.
✓ Branch 4 taken 593263 times.
✓ Branch 5 taken 72421 times.
✓ Branch 6 taken 33219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6253 times.
✓ Branch 9 taken 2041479 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
21766265 switch (field->type()) {
8661 /* NOTE that we only allow string types in DATA_MYSQL and
8662 DATA_VARMYSQL */
8663 6454878 case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
8664 case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */
8665
2/2
✓ Branch 0 taken 46392 times.
✓ Branch 1 taken 6408486 times.
6454878 if (field->binary()) {
8666 46392 return (DATA_BINARY);
8667
2/2
✓ Branch 0 taken 67689 times.
✓ Branch 1 taken 6340797 times.
6408486 } else if (field->charset() == &my_charset_latin1) {
8668 67689 return (DATA_VARCHAR);
8669 } else {
8670 6340797 return (DATA_VARMYSQL);
8671 }
8672 1905760 case MYSQL_TYPE_BIT:
8673 case MYSQL_TYPE_STRING:
8674
2/2
✓ Branch 0 taken 15038 times.
✓ Branch 1 taken 1890722 times.
1905760 if (field->binary()) {
8675 15038 return (DATA_FIXBINARY);
8676
2/2
✓ Branch 0 taken 11945 times.
✓ Branch 1 taken 1878777 times.
1890722 } else if (field->charset() == &my_charset_latin1) {
8677 11945 return (DATA_CHAR);
8678 } else {
8679 1878777 return (DATA_MYSQL);
8680 }
8681 19926 case MYSQL_TYPE_NEWDECIMAL:
8682 19926 return (DATA_FIXBINARY);
8683 10639066 case MYSQL_TYPE_LONG:
8684 case MYSQL_TYPE_LONGLONG:
8685 case MYSQL_TYPE_TINY:
8686 case MYSQL_TYPE_SHORT:
8687 case MYSQL_TYPE_INT24:
8688 case MYSQL_TYPE_DATE:
8689 case MYSQL_TYPE_YEAR:
8690 case MYSQL_TYPE_NEWDATE:
8691 case MYSQL_TYPE_BOOL:
8692 10639066 return (DATA_INT);
8693 593263 case MYSQL_TYPE_TIME:
8694 case MYSQL_TYPE_DATETIME:
8695 case MYSQL_TYPE_TIMESTAMP:
8696 case MYSQL_TYPE_TIME2:
8697 case MYSQL_TYPE_DATETIME2:
8698 case MYSQL_TYPE_TIMESTAMP2:
8699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 593263 times.
593263 switch (field->real_type()) {
8700 case MYSQL_TYPE_TIME:
8701 case MYSQL_TYPE_DATETIME:
8702 case MYSQL_TYPE_TIMESTAMP:
8703 return (DATA_INT);
8704 593263 default:
8705 assert((ulint)MYSQL_TYPE_DECIMAL < 256);
8706 [[fallthrough]];
8707 case MYSQL_TYPE_TIME2:
8708 case MYSQL_TYPE_DATETIME2:
8709 case MYSQL_TYPE_TIMESTAMP2:
8710 593263 return (DATA_FIXBINARY);
8711 }
8712 72421 case MYSQL_TYPE_FLOAT:
8713 72421 return (DATA_FLOAT);
8714 33219 case MYSQL_TYPE_DOUBLE:
8715 33219 return (DATA_DOUBLE);
8716 case MYSQL_TYPE_DECIMAL:
8717 return (DATA_DECIMAL);
8718 6253 case MYSQL_TYPE_GEOMETRY:
8719 6253 return (DATA_GEOMETRY);
8720 2041479 case MYSQL_TYPE_TINY_BLOB:
8721 case MYSQL_TYPE_MEDIUM_BLOB:
8722 case MYSQL_TYPE_BLOB:
8723 case MYSQL_TYPE_LONG_BLOB:
8724 case MYSQL_TYPE_JSON: // JSON fields are stored as BLOBs
8725 2041479 return (DATA_BLOB);
8726 case MYSQL_TYPE_NULL:
8727 /* MySQL currently accepts "NULL" datatype, but will
8728 reject such datatype in the next release. We will cope
8729 with it and not trigger assertion failure in 5.1 */
8730 break;
8731 1 default:
8732 1 ut_error;
8733 }
8734
8735 return (0);
8736 }
8737
8738 /** Converts a MySQL data-dictionary type to an InnoDB type. Also returns
8739 a few attributes which are useful for precise type calculation.
8740
8741 @note This function is version of get_innobase_type_from_mysql_type() with
8742 added knowledge about how additional attributes calculated (e.g. in
8743 create_table_info_t::create_table_def()) and about behavior of Field
8744 class and its descendats.
8745
8746 @note It allows to get InnoDB generic and precise types directly from MySQL
8747 data-dictionary info, bypassing expensive construction of Field objects.
8748
8749 @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'.
8750 @param[out] binary_type DATA_BINARY_TYPE if a 'binary type'.
8751 @param[out] charset_no Collation id for string types.
8752 @param[in] dd_type MySQL data-dictionary type.
8753 @param[in] field_charset Charset.
8754 @param[in] is_unsigned MySQL data-dictionary unsigned flag.
8755
8756 @return DATA_BINARY, DATA_VARCHAR, ... */
8757 682612 ulint get_innobase_type_from_mysql_dd_type(ulint *unsigned_flag,
8758 ulint *binary_type,
8759 ulint *charset_no,
8760 dd::enum_column_types dd_type,
8761 const CHARSET_INFO *field_charset,
8762 bool is_unsigned) {
8763 /* InnoDB's unsigned flag is based on UNSIGNED_FLAG bit in Field::flags.
8764 This bit is unset for Field objects by default. */
8765 682612 *unsigned_flag = 0;
8766 /* InnoDB's binary type flag is based on result of Field::binary() call.
8767 The latter returns true by default. */
8768 682612 *binary_type = DATA_BINARY_TYPE;
8769 /* InnoDB takes into account charset numbers only for columns which it
8770 considers of string type. */
8771 682612 *charset_no = 0;
8772
8773
5/13
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 676 times.
✓ Branch 4 taken 681849 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
682612 switch (dd_type) {
8774 6 case dd::enum_column_types::ENUM:
8775 case dd::enum_column_types::SET:
8776 /* SQL-layer has its own unsigned flag set to zero, even though
8777 internally this is an unsigned integer type. */
8778 6 *unsigned_flag = DATA_UNSIGNED;
8779 /* ENUM and SET are handled as string types by SQL-layer,
8780 hence the charset check. */
8781
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (field_charset != &my_charset_bin) *binary_type = 0;
8782 6 return (DATA_INT);
8783 78 case dd::enum_column_types::VAR_STRING: /* old <= 4.1 VARCHAR. */
8784 case dd::enum_column_types::VARCHAR: /* new >= 5.0.3 true VARCHAR. */
8785 78 *charset_no = field_charset->number;
8786
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 76 times.
78 if (field_charset == &my_charset_bin) {
8787 2 return (DATA_BINARY);
8788 } else {
8789 76 *binary_type = 0;
8790
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 52 times.
76 if (field_charset == &my_charset_latin1) {
8791 24 return (DATA_VARCHAR);
8792 } else {
8793 52 return (DATA_VARMYSQL);
8794 }
8795 }
8796 case dd::enum_column_types::BIT:
8797 /* MySQL always sets unsigned flag for both its BIT types. */
8798 *unsigned_flag = DATA_UNSIGNED;
8799 *charset_no = my_charset_bin.number;
8800 return (DATA_FIXBINARY);
8801 676 case dd::enum_column_types::STRING:
8802 676 *charset_no = field_charset->number;
8803
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 634 times.
676 if (field_charset == &my_charset_bin) {
8804 42 return (DATA_FIXBINARY);
8805 } else {
8806 634 *binary_type = 0;
8807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 634 times.
634 if (field_charset == &my_charset_latin1) {
8808 return (DATA_CHAR);
8809 } else {
8810 634 return (DATA_MYSQL);
8811 }
8812 }
8813 681849 case dd::enum_column_types::DECIMAL:
8814 case dd::enum_column_types::FLOAT:
8815 case dd::enum_column_types::DOUBLE:
8816 case dd::enum_column_types::NEWDECIMAL:
8817 case dd::enum_column_types::LONG:
8818 case dd::enum_column_types::LONGLONG:
8819 case dd::enum_column_types::TINY:
8820 case dd::enum_column_types::SHORT:
8821 case dd::enum_column_types::INT24:
8822 /* Types based on Field_num set unsigned flag from value stored
8823 in the data-dictionary (YEAR being the exception). */
8824
2/2
✓ Branch 0 taken 673926 times.
✓ Branch 1 taken 7923 times.
681849 if (is_unsigned) *unsigned_flag = DATA_UNSIGNED;
8825 switch (dd_type) {
8826 case dd::enum_column_types::DECIMAL:
8827 return (DATA_DECIMAL);
8828 case dd::enum_column_types::FLOAT:
8829 return (DATA_FLOAT);
8830 case dd::enum_column_types::DOUBLE:
8831 return (DATA_DOUBLE);
8832 case dd::enum_column_types::NEWDECIMAL:
8833 *charset_no = my_charset_bin.number;
8834 return (DATA_FIXBINARY);
8835 681849 default:
8836 681849 break;
8837 }
8838 681849 return (DATA_INT);
8839 case dd::enum_column_types::DATE:
8840 case dd::enum_column_types::NEWDATE:
8841 case dd::enum_column_types::TIME:
8842 case dd::enum_column_types::DATETIME:
8843 return (DATA_INT);
8844 case dd::enum_column_types::YEAR:
8845 case dd::enum_column_types::TIMESTAMP:
8846 /* MySQL always sets unsigned flag for YEAR and old TIMESTAMP type. */
8847 *unsigned_flag = DATA_UNSIGNED;
8848 return (DATA_INT);
8849 case dd::enum_column_types::TIME2:
8850 case dd::enum_column_types::DATETIME2:
8851 case dd::enum_column_types::TIMESTAMP2:
8852 *charset_no = my_charset_bin.number;
8853 return (DATA_FIXBINARY);
8854 case dd::enum_column_types::GEOMETRY:
8855 /* Field_geom::binary() is always true. */
8856 return (DATA_GEOMETRY);
8857 3 case dd::enum_column_types::TINY_BLOB:
8858 case dd::enum_column_types::MEDIUM_BLOB:
8859 case dd::enum_column_types::BLOB:
8860 case dd::enum_column_types::LONG_BLOB:
8861 3 *charset_no = field_charset->number;
8862
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (field_charset != &my_charset_bin) *binary_type = 0;
8863 3 return (DATA_BLOB);
8864 case dd::enum_column_types::JSON:
8865 /* JSON fields are stored as BLOBs.
8866 Field_json::binary() always returns true even though data in
8867 such columns are stored in UTF8. */
8868 *charset_no = my_charset_utf8mb4_bin.number;
8869 return (DATA_BLOB);
8870 case dd::enum_column_types::TYPE_NULL:
8871 /* Compatibility with get_innobase_type_from_mysql_type(). */
8872 *charset_no = field_charset->number;
8873 if (field_charset != &my_charset_bin) *binary_type = 0;
8874 break;
8875 default:
8876 ut_error;
8877 }
8878
8879 return (0);
8880 }
8881
8882 /** Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
8883 storage format.
8884 @return value */
8885 126 static inline uint innobase_read_from_2_little_endian(
8886 const uchar *buf) /*!< in: from where to read */
8887 {
8888 126 return ((uint)((ulint)(buf[0]) + 256 * ((ulint)(buf[1]))));
8889 }
8890
8891 /** Determines if a field is needed in a m_prebuilt struct 'template'.
8892 @return field to use, or NULL if the field is not needed */
8893 1567760803 static const Field *build_template_needs_field(
8894 bool index_contains, /*!< in:
8895 dict_index_contains_col_or_prefix(
8896 index, i) */
8897 bool read_just_key, /*!< in: true when MySQL calls
8898 ha_innobase::extra with the
8899 argument HA_EXTRA_KEYREAD; it is enough
8900 to read just columns defined in
8901 the index (i.e., no read of the
8902 clustered index record necessary) */
8903 bool fetch_all_in_key,
8904 /*!< in: true=fetch all fields in
8905 the index */
8906 bool fetch_primary_key_cols,
8907 /*!< in: true=fetch the
8908 primary key columns */
8909 dict_index_t *index, /*!< in: InnoDB index to use */
8910 const TABLE *table, /*!< in: MySQL table object */
8911 ulint i, /*!< in: field index in InnoDB table */
8912 ulint num_v) /*!< in: num virtual column so far */
8913 {
8914 1567760803 const Field *field = table->field[i];
8915
8916
2/2
✓ Branch 0 taken 926978434 times.
✓ Branch 1 taken 640782369 times.
1567760803 if (!index_contains) {
8917
2/2
✓ Branch 0 taken 5090112 times.
✓ Branch 1 taken 921888322 times.
926978434 if (read_just_key) {
8918 /* If this is a 'key read', we do not need
8919 columns that are not in the key */
8920
8921 5090112 return (nullptr);
8922 }
8923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 640782369 times.
640782369 } else if (fetch_all_in_key) {
8924 /* This field is needed in the query */
8925
8926 return (field);
8927 }
8928
8929
6/6
✓ Branch 0 taken 58977217 times.
✓ Branch 1 taken 1503694206 times.
✓ Branch 2 taken 1756739 times.
✓ Branch 3 taken 57220710 times.
✓ Branch 4 taken 1505450929 times.
✓ Branch 5 taken 57220726 times.
1621648140 if (bitmap_is_set(table->read_set, static_cast<uint>(i)) ||
8930 58977217 bitmap_is_set(table->write_set, static_cast<uint>(i))) {
8931 /* This field is needed in the query */
8932
8933 1505450929 return (field);
8934 }
8935
8936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57220705 times.
57220726 ut_ad(i >= num_v);
8937
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 57220705 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57220705 times.
57220705 if (fetch_primary_key_cols &&
8938 dict_table_col_in_clustered_key(index->table, i - num_v)) {
8939 /* This field is needed in the query */
8940
8941 return (field);
8942 }
8943
8944 /* This field is not needed in the query, skip it */
8945
8946 57220705 return (nullptr);
8947 }
8948
8949 /** Determines if a field is needed in a m_prebuilt struct 'template'.
8950 @return whether the field is needed for index condition pushdown */
8951 41682 inline bool build_template_needs_field_in_icp(
8952 const dict_index_t *index, /*!< in: InnoDB index */
8953 const row_prebuilt_t *prebuilt, /*!< in: row fetch template */
8954 bool contains, /*!< in: whether the index contains
8955 column i */
8956 ulint i, /*!< in: column number */
8957 bool is_virtual)
8958 /*!< in: a virtual column or not */
8959 {
8960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41682 times.
41682 ut_ad(contains == dict_index_contains_col_or_prefix(index, i, is_virtual));
8961
8962
2/2
✓ Branch 0 taken 41370 times.
✓ Branch 1 taken 312 times.
41682 return (index == prebuilt->index ? contains
8963 312 : dict_index_contains_col_or_prefix(
8964 41994 prebuilt->index, i, is_virtual));
8965 }
8966
8967 /** Adds a field to a m_prebuilt struct 'template'.
8968 @return the field template */
8969 2018805775 static mysql_row_templ_t *build_template_field(
8970 row_prebuilt_t *prebuilt, /*!< in/out: template */
8971 dict_index_t *clust_index, /*!< in: InnoDB clustered index */
8972 dict_index_t *index, /*!< in: InnoDB index to use */
8973 TABLE *table, /*!< in: MySQL table object */
8974 const Field *field, /*!< in: field in MySQL table */
8975 ulint i, /*!< in: field index in InnoDB table */
8976 ulint v_no) /*!< in: field index for virtual col */
8977 {
8978 mysql_row_templ_t *templ;
8979 const dict_col_t *col;
8980
8981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2018805620 times.
2018805775 ut_ad(clust_index->table == index->table);
8982
8983 2018805620 templ = prebuilt->mysql_template + prebuilt->n_template++;
8984 UNIV_MEM_INVALID(templ, sizeof *templ);
8985
8986
4/4
✓ Branch 0 taken 366728 times.
✓ Branch 1 taken 2018438892 times.
✓ Branch 2 taken 310486 times.
✓ Branch 3 taken 56242 times.
2018805620 if (innobase_is_v_fld(field)) {
8987 310486 templ->is_virtual = true;
8988 310486 col = &dict_table_get_nth_v_col(index->table, v_no)->m_col;
8989 } else {
8990 2018495134 templ->is_virtual = false;
8991 2018495134 col = index->table->get_col(i);
8992 }
8993
8994
2/2
✓ Branch 0 taken 2018493646 times.
✓ Branch 1 taken 310244 times.
2018803890 if (!templ->is_virtual) {
8995 2018493646 templ->col_no = i;
8996 2018493646 templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index);
8997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2018498899 times.
2018499357 ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED);
8998 2018498899 templ->rec_prefix_field_no = ULINT_UNDEFINED;
8999
9000
2/2
✓ Branch 0 taken 891662378 times.
✓ Branch 1 taken 1126835629 times.
2018498899 if (index->is_clustered()) {
9001 891662378 templ->rec_field_is_prefix = false;
9002 891662378 templ->rec_field_no = templ->clust_rec_field_no;
9003 } else {
9004 /* If we're in a secondary index, keep track of the original index
9005 position even if this is just a prefix non-geometry index; we will use
9006 this later to avoid a cluster index lookup in some cases. */
9007
9008 1126835367 templ->rec_field_no = index->get_col_pos(
9009 i, false, false,
9010
2/2
✓ Branch 0 taken 1126835090 times.
✓ Branch 1 taken 277 times.
1126835629 (field->type() == MYSQL_TYPE_GEOMETRY) ? nullptr
9011 : &templ->rec_prefix_field_no);
9012 1126833108 templ->rec_field_is_prefix =
9013
2/2
✓ Branch 0 taken 904476250 times.
✓ Branch 1 taken 222356858 times.
2031309358 (templ->rec_field_no == ULINT_UNDEFINED) &&
9014
2/2
✓ Branch 0 taken 1904 times.
✓ Branch 1 taken 904474346 times.
904476250 (templ->rec_prefix_field_no != ULINT_UNDEFINED);
9015 #ifdef UNIV_DEBUG
9016
2/2
✓ Branch 0 taken 222359246 times.
✓ Branch 1 taken 904473862 times.
1126833108 if (templ->rec_prefix_field_no != ULINT_UNDEFINED) {
9017 222359246 const auto *const field = index->get_field(templ->rec_prefix_field_no);
9018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 222359244 times.
222359245 ut_ad(templ->rec_field_is_prefix == (field->prefix_len != 0));
9019 } else {
9020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 904474569 times.
904473862 ut_ad(!templ->rec_field_is_prefix);
9021 }
9022 #endif
9023 }
9024 } else {
9025 310244 templ->clust_rec_field_no = v_no;
9026 // Prefix optimisation on generated column indexes is not
9027 // currently supported
9028 310244 templ->rec_field_is_prefix = false;
9029 310244 templ->rec_prefix_field_no = ULINT_UNDEFINED;
9030
2/2
✓ Branch 0 taken 308648 times.
✓ Branch 1 taken 1838 times.
310244 if (index->is_clustered()) {
9031 308648 templ->rec_field_no = templ->clust_rec_field_no;
9032 } else {
9033 1838 templ->rec_field_no = index->get_col_pos(v_no, false, true);
9034 }
9035 }
9036
9037 /* Set in set_templ_icp(). */
9038 2018806677 templ->icp_rec_field_no = ULINT_UNDEFINED;
9039
9040
2/2
✓ Branch 0 taken 893069963 times.
✓ Branch 1 taken 1125734541 times.
2018806677 if (field->is_nullable()) {
9041 893069963 templ->mysql_null_byte_offset = field->null_offset();
9042
9043 893073490 templ->mysql_null_bit_mask = (ulint)field->null_bit;
9044 } else {
9045 1125734541 templ->mysql_null_bit_mask = 0;
9046 }
9047
9048 2018808031 templ->mysql_col_offset = (ulint)get_field_offset(table, field);
9049 2018805056 templ->mysql_col_len = (ulint)field->pack_length();
9050
6/6
✓ Branch 0 taken 310486 times.
✓ Branch 1 taken 2018493807 times.
✓ Branch 2 taken 2121 times.
✓ Branch 3 taken 308365 times.
✓ Branch 4 taken 2121 times.
✓ Branch 5 taken 2018802172 times.
2018804293 if (templ->is_virtual && innobase_is_multi_value_fld(field)) {
9051 2121 templ->mysql_mvidx_len = static_cast<ulint>(field->key_length());
9052 2121 templ->is_multi_val = true;
9053 } else {
9054 2018802172 templ->mysql_mvidx_len = 0;
9055 2018802172 templ->is_multi_val = false;
9056 }
9057 2018804293 templ->type = col->mtype;
9058 2018804293 templ->mysql_type = (ulint)field->type();
9059
9060
2/2
✓ Branch 0 taken 414577993 times.
✓ Branch 1 taken 1604226583 times.
2018804576 if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
9061 414577993 templ->mysql_length_bytes = field->get_length_bytes();
9062 } else {
9063 1604226583 templ->mysql_length_bytes = 0;
9064 }
9065
9066 2018807319 templ->charset = dtype_get_charset_coll(col->prtype);
9067 2018804904 templ->mbminlen = col->get_mbminlen();
9068 2018805102 templ->mbmaxlen = col->get_mbmaxlen();
9069 2018805955 templ->is_unsigned = col->prtype & DATA_UNSIGNED;
9070 2018805955 templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED);
9071 2018805779 templ->zip_dict_data = field->zip_dict_data;
9072
9073
6/6
✓ Branch 0 taken 1126835876 times.
✓ Branch 1 taken 891971445 times.
✓ Branch 2 taken 904477473 times.
✓ Branch 3 taken 222358403 times.
✓ Branch 4 taken 904477386 times.
✓ Branch 5 taken 1114329935 times.
2018805779 if (!index->is_clustered() && templ->rec_field_no == ULINT_UNDEFINED) {
9074 904477386 prebuilt->need_to_access_clustered = true;
9075 }
9076
9077 /* For spatial index, we need to access cluster index. */
9078
2/2
✓ Branch 0 taken 610 times.
✓ Branch 1 taken 2018803155 times.
2018807321 if (dict_index_is_spatial(index)) {
9079 610 prebuilt->need_to_access_clustered = true;
9080 }
9081
9082 2018803765 if (prebuilt->mysql_prefix_len <
9083
2/2
✓ Branch 0 taken 2018713116 times.
✓ Branch 1 taken 90649 times.
2018803765 templ->mysql_col_offset + templ->mysql_col_len) {
9084 2018713116 prebuilt->mysql_prefix_len = templ->mysql_col_offset + templ->mysql_col_len;
9085 }
9086
9087
2/2
✓ Branch 0 taken 421239402 times.
✓ Branch 1 taken 1597564602 times.
2018803765 if (DATA_LARGE_MTYPE(templ->type)) {
9088 421239402 prebuilt->templ_contains_blob = true;
9089 }
9090
9091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2018804004 times.
2018804004 if (templ->type == DATA_POINT) {
9092 /* We set this only when it's DATA_POINT, but not
9093 DATA_VAR_POINT */
9094 prebuilt->templ_contains_fixed_point = true;
9095 }
9096
9097 2018804004 return (templ);
9098 }
9099
9100 /** Set Index Condition Push down (ICP) field number in template.
9101 @param[in,out] templ mysql column template
9102 @param[in] index index used to build the template
9103 @param[in] scan_index active index for current scan
9104 @param[in] col_position position of current column */
9105 9803 static void set_templ_icp(mysql_row_templ_t *templ, const dict_index_t *index,
9106 const dict_index_t *scan_index, ulint col_position) {
9107
2/4
✓ Branch 0 taken 9803 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9803 times.
9803 if (scan_index == nullptr || templ == nullptr) {
9108 return;
9109 }
9110
9111 9803 bool is_virtual = templ->is_virtual;
9112 9803 auto icp_field_no = templ->rec_field_no;
9113
9114
2/2
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 9455 times.
9803 if (scan_index != index) {
9115 /* First, try to find the column position without prefix. */
9116 348 icp_field_no = scan_index->get_col_pos(col_position, false, is_virtual);
9117 }
9118
9119 /* Try any prefix of the column. Used in end_range comparison. */
9120
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 9404 times.
9803 if (icp_field_no == ULINT_UNDEFINED) {
9121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 399 times.
399 ut_ad(!scan_index->is_clustered());
9122 399 icp_field_no = scan_index->get_col_pos(col_position, true, is_virtual);
9123 }
9124 9803 templ->icp_rec_field_no = icp_field_no;
9125 }
9126
9127 /** Builds a 'template' to the m_prebuilt struct. The template is used in fast
9128 retrieval of just those column values MySQL needs in its processing.
9129 @param[in] whole_row true if access is needed to a whole row, false if accessing
9130 individual fields is enough */
9131 156935290 void ha_innobase::build_template(bool whole_row) {
9132 dict_index_t *index;
9133 dict_index_t *clust_index;
9134 ulint n_fields;
9135 156935290 bool fetch_all_in_key = false;
9136 156935290 bool fetch_primary_key_cols = false;
9137 ulint i;
9138
9139
2/2
✓ Branch 0 taken 36809482 times.
✓ Branch 1 taken 120125808 times.
156935290 if (m_prebuilt->select_lock_type == LOCK_X) {
9140 /* We always retrieve the whole clustered index record if we
9141 use exclusive row level locks, for example, if the read is
9142 done in an UPDATE statement. */
9143
9144 36809482 whole_row = true;
9145
2/2
✓ Branch 0 taken 119977018 times.
✓ Branch 1 taken 148790 times.
120125808 } else if (!whole_row) {
9146
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 119976788 times.
119977018 if (m_prebuilt->hint_need_to_fetch_extra_cols == ROW_RETRIEVE_ALL_COLS) {
9147 /* We know we must at least fetch all columns in the
9148 key, or all columns in the table */
9149
9150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 230 times.
230 if (m_prebuilt->read_just_key) {
9151 /* MySQL has instructed us that it is enough
9152 to fetch the columns in the key; looks like
9153 MySQL can set this flag also when there is
9154 only a prefix of the column in the key: in
9155 that case we retrieve the whole column from
9156 the clustered index */
9157
9158 fetch_all_in_key = true;
9159 } else {
9160 230 whole_row = true;
9161 }
9162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 119976788 times.
119976788 } else if (m_prebuilt->hint_need_to_fetch_extra_cols ==
9163 ROW_RETRIEVE_PRIMARY_KEY) {
9164 /* We must at least fetch all primary key cols. Note
9165 that if the clustered index was internally generated
9166 by InnoDB on the row id (no primary key was
9167 defined), then row_search_for_mysql() will always
9168 retrieve the row id to a special buffer in the
9169 m_prebuilt struct. */
9170
9171 fetch_primary_key_cols = true;
9172 }
9173 }
9174
9175 156935290 clust_index = m_prebuilt->table->first_index();
9176
9177
2/2
✓ Branch 0 taken 36958601 times.
✓ Branch 1 taken 119976825 times.
156935426 index = whole_row ? clust_index : m_prebuilt->index;
9178
9179 156935426 m_prebuilt->need_to_access_clustered = (index == clust_index);
9180
9181 /* Either m_prebuilt->index should be a secondary index, or it
9182 should be the clustered index. */
9183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156935426 times.
156935426 ut_ad(index->is_clustered() == (index == clust_index));
9184
9185 /* Below we check column by column if we need to access
9186 the clustered index. */
9187
9188 156935426 n_fields = (ulint)table->s->fields; /* number of columns */
9189
9190
2/2
✓ Branch 0 taken 3371848 times.
✓ Branch 1 taken 153563578 times.
156935426 if (!m_prebuilt->mysql_template) {
9191 3371847 m_prebuilt->mysql_template = (mysql_row_templ_t *)ut::malloc_withkey(
9192 3371848 UT_NEW_THIS_FILE_PSI_KEY, n_fields * sizeof(mysql_row_templ_t));
9193 }
9194
9195 #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND)
9196 /* zero-filling for compare contents for debug */
9197 156935249 memset(m_prebuilt->mysql_template, 0, n_fields * sizeof(mysql_row_templ_t));
9198 #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
9199
9200 156935249 m_prebuilt->template_type =
9201
2/2
✓ Branch 0 taken 36958492 times.
✓ Branch 1 taken 119976757 times.
156935249 whole_row ? ROW_MYSQL_WHOLE_ROW : ROW_MYSQL_REC_FIELDS;
9202 156935249 m_prebuilt->null_bitmap_len = table->s->null_bytes;
9203
9204 /* Prepare to build m_prebuilt->mysql_template[]. */
9205 156935249 m_prebuilt->templ_contains_blob = false;
9206 156935249 m_prebuilt->templ_contains_fixed_point = false;
9207 156935249 m_prebuilt->mysql_prefix_len = 0;
9208 156935249 m_prebuilt->n_template = 0;
9209 156935249 m_prebuilt->idx_cond_n_cols = 0;
9210
9211 /* Note that in InnoDB, i is the column number in the table.
9212 MySQL calls columns 'fields'. */
9213
9214
4/4
✓ Branch 0 taken 154915261 times.
✓ Branch 1 taken 2019988 times.
✓ Branch 2 taken 4389 times.
✓ Branch 3 taken 154910872 times.
156935249 if (active_index != MAX_KEY && active_index == pushed_idx_cond_keyno) {
9215 4389 ulint num_v = 0;
9216
9217 /* Push down an index condition or an end_range check. */
9218
2/2
✓ Branch 0 taken 20841 times.
✓ Branch 1 taken 4389 times.
25230 for (i = 0; i < n_fields; i++) {
9219 bool index_contains;
9220
9221
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
20841 if (innobase_is_v_fld(table->field[i])) {
9222 18 index_contains = dict_index_contains_col_or_prefix(index, num_v, true);
9223 } else {
9224 index_contains =
9225 20823 dict_index_contains_col_or_prefix(index, i - num_v, false);
9226 }
9227
9228 /* Test if an end_range or an index condition
9229 refers to the field. Note that "index" and
9230 "index_contains" may refer to the clustered index.
9231 Index condition pushdown is relative to
9232 m_prebuilt->index (the index that is being
9233 looked up first). */
9234
9235 /* When join_read_always_key() invokes this
9236 code via handler::ha_index_init() and
9237 ha_innobase::index_init(), end_range is not
9238 yet initialized. Because of that, we must
9239 always check for index_contains, instead of
9240 the subset
9241 field->part_of_key.is_set(active_index)
9242 which would be acceptable if end_range==NULL. */
9243
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
20841 bool is_v = innobase_is_v_fld(table->field[i]);
9244
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20823 times.
✓ Branch 2 taken 8221 times.
✓ Branch 3 taken 12620 times.
20841 if (build_template_needs_field_in_icp(index, m_prebuilt, index_contains,
9245 is_v ? num_v : i - num_v, is_v)) {
9246 /* Needed in ICP */
9247 const Field *field;
9248 mysql_row_templ_t *templ;
9249
9250
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 8097 times.
8221 if (whole_row) {
9251 124 field = table->field[i];
9252 } else {
9253 16194 field = build_template_needs_field(
9254 8097 index_contains, m_prebuilt->read_just_key, fetch_all_in_key,
9255 8097 fetch_primary_key_cols, index, table, i, num_v);
9256
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 7631 times.
8097 if (!field) {
9257
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
466 if (innobase_is_v_fld(table->field[i])) {
9258 num_v++;
9259 }
9260 466 continue;
9261 }
9262 }
9263
9264 7755 templ = build_template_field(m_prebuilt, clust_index, index, table,
9265 field, i - num_v, 0);
9266
9267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7755 times.
7755 ut_ad(!templ->is_virtual);
9268
9269 7755 m_prebuilt->idx_cond_n_cols++;
9270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7755 times.
7755 ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template);
9271
9272 7755 auto column_position = i - num_v;
9273
9274 7755 set_templ_icp(templ, index, m_prebuilt->index, column_position);
9275
9276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7755 times.
7755 ut_ad(templ->icp_rec_field_no != ULINT_UNDEFINED);
9277
9278 /* Index condition pushdown can be used on
9279 all columns of a secondary index, and on
9280 the PRIMARY KEY columns. On the clustered
9281 index, it must never be used on other than
9282 PRIMARY KEY columns, because those columns
9283 may be stored off-page, and we will not
9284 fetch externally stored columns before
9285 checking the index condition. */
9286 /* TODO: test the above with an assertion
9287 like this. Note that index conditions are
9288 currently pushed down as part of the
9289 "optimizer phase" while end_range is done
9290 as part of the execution phase. Therefore,
9291 we were unable to use an accurate condition
9292 for end_range in the "if" condition above,
9293 and the following assertion would fail.
9294 ut_ad(!(m_prebuilt->index->is_clustered())
9295 || templ->rec_field_no
9296 < m_prebuilt->index->n_uniq);
9297 */
9298 }
9299
9300
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20347 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
20375 if (innobase_is_v_fld(table->field[i])) {
9301 18 num_v++;
9302 }
9303 }
9304
9305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4389 times.
4389 ut_ad(m_prebuilt->idx_cond_n_cols > 0);
9306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4389 times.
4389 ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template);
9307
9308 4389 num_v = 0;
9309
9310 /* Include the fields that are not needed in index condition
9311 pushdown. */
9312
2/2
✓ Branch 0 taken 20841 times.
✓ Branch 1 taken 4389 times.
25230 for (i = 0; i < n_fields; i++) {
9313 mysql_row_templ_t *templ;
9314 bool index_contains;
9315
9316
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
20841 if (innobase_is_v_fld(table->field[i])) {
9317 18 index_contains = dict_index_contains_col_or_prefix(index, num_v, true);
9318 } else {
9319 index_contains =
9320 20823 dict_index_contains_col_or_prefix(index, i - num_v, false);
9321 }
9322
9323
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
20841 bool is_v = innobase_is_v_fld(table->field[i]);
9324
9325
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20823 times.
✓ Branch 2 taken 12620 times.
✓ Branch 3 taken 8221 times.
20841 if (!build_template_needs_field_in_icp(index, m_prebuilt, index_contains,
9326 is_v ? num_v : i - num_v, is_v)) {
9327 /* Not needed in ICP */
9328 const Field *field;
9329
9330
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 12588 times.
12620 if (whole_row) {
9331 32 field = table->field[i];
9332 } else {
9333 25176 field = build_template_needs_field(
9334 12588 index_contains, m_prebuilt->read_just_key, fetch_all_in_key,
9335 12588 fetch_primary_key_cols, index, table, i, num_v);
9336
2/2
✓ Branch 0 taken 2120 times.
✓ Branch 1 taken 10468 times.
12588 if (!field) {
9337
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2116 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
2120 if (innobase_is_v_fld(table->field[i])) {
9338 4 num_v++;
9339 }
9340 2120 continue;
9341 }
9342 }
9343
9344 10500 templ = build_template_field(m_prebuilt, clust_index, index, table,
9345 field, i - num_v, num_v);
9346
9347
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 10486 times.
10500 if (templ->is_virtual) {
9348 14 num_v++;
9349 }
9350 }
9351 }
9352
9353 4389 m_prebuilt->idx_cond = true;
9354 4389 } else {
9355 mysql_row_templ_t *templ;
9356 156930860 ulint num_v = 0;
9357 /* No index condition pushdown */
9358 156930860 m_prebuilt->idx_cond = false;
9359
9360
2/2
✓ Branch 0 taken 2081093656 times.
✓ Branch 1 taken 156930617 times.
2238024273 for (i = 0; i < n_fields; i++) {
9361 const Field *field;
9362
4/4
✓ Branch 0 taken 573943 times.
✓ Branch 1 taken 2080519713 times.
✓ Branch 2 taken 509169 times.
✓ Branch 3 taken 64774 times.
2081093656 bool is_virtual = innobase_is_v_fld(table->field[i]);
9363
9364
2/2
✓ Branch 0 taken 513354908 times.
✓ Branch 1 taken 1567738748 times.
2081093656 if (whole_row) {
9365 /* Even this is whole_row, if the seach is
9366 on a virtual column, and read_just_key is
9367 set, and field is not in this index, we
9368 will not try to fill the value since they
9369 are not stored in such index nor in the
9370 cluster index. */
9371
5/6
✓ Branch 0 taken 107386 times.
✓ Branch 1 taken 513247522 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 107380 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 513354908 times.
513354914 if (is_virtual && m_prebuilt->read_just_key &&
9372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 !dict_index_contains_col_or_prefix(m_prebuilt->index, num_v,
9373 true)) {
9374 /* Turn off ROW_MYSQL_WHOLE_ROW */
9375 m_prebuilt->template_type = ROW_MYSQL_REC_FIELDS;
9376 num_v++;
9377 continue;
9378 }
9379
9380 513354908 field = table->field[i];
9381 } else {
9382 bool contain;
9383
9384
4/4
✓ Branch 0 taken 418688 times.
✓ Branch 1 taken 1567320060 times.
✓ Branch 2 taken 401783 times.
✓ Branch 3 taken 16905 times.
1567738748 if (innobase_is_v_fld(table->field[i])) {
9385 401783 contain = dict_index_contains_col_or_prefix(index, num_v, true);
9386 } else {
9387 1567336965 contain = dict_index_contains_col_or_prefix(index, i - num_v, false);
9388 }
9389
9390 3135479578 field = build_template_needs_field(
9391 1567738961 contain, m_prebuilt->read_just_key, fetch_all_in_key,
9392 1567738961 fetch_primary_key_cols, index, table, i, num_v);
9393
2/2
✓ Branch 0 taken 62308172 times.
✓ Branch 1 taken 1505432445 times.
1567740617 if (!field) {
9394
2/2
✓ Branch 0 taken 198697 times.
✓ Branch 1 taken 62109475 times.
62308172 if (is_virtual) {
9395 198697 num_v++;
9396 }
9397 62308172 continue;
9398 }
9399 }
9400
9401 2018787353 templ = build_template_field(m_prebuilt, clust_index, index, table, field,
9402 i - num_v, num_v);
9403
9404 /* Virtual columns may have to be read from the secondary index before
9405 evaluating an end-range condition in row_search_end_range_check(). Set
9406 ICP field number for virtual column. */
9407 2018785742 auto scan_index = m_prebuilt->index;
9408
4/4
✓ Branch 0 taken 2016133417 times.
✓ Branch 1 taken 2652325 times.
✓ Branch 2 taken 1179175661 times.
✓ Branch 3 taken 836958426 times.
2018785742 bool is_sec_idx = (scan_index != nullptr && !scan_index->is_clustered());
9409
9410
4/4
✓ Branch 0 taken 310472 times.
✓ Branch 1 taken 2018475940 times.
✓ Branch 2 taken 2048 times.
✓ Branch 3 taken 308424 times.
2018786412 if (is_virtual && is_sec_idx) {
9411 2048 set_templ_icp(templ, index, scan_index, num_v);
9412 }
9413
9414
2/2
✓ Branch 0 taken 310472 times.
✓ Branch 1 taken 2018474769 times.
2018785241 if (templ->is_virtual) {
9415 310472 num_v++;
9416 }
9417 }
9418 }
9419
9420
4/4
✓ Branch 0 taken 66718577 times.
✓ Branch 1 taken 90216429 times.
✓ Branch 2 taken 62721945 times.
✓ Branch 3 taken 3996632 times.
156935006 if (index != clust_index && m_prebuilt->need_to_access_clustered) {
9421 /* Change rec_field_no's to correspond to the clustered index
9422 record */
9423
2/2
✓ Branch 0 taken 1114787975 times.
✓ Branch 1 taken 62721945 times.
1177509920 for (i = 0; i < m_prebuilt->n_template; i++) {
9424 1114787975 mysql_row_templ_t *templ = &m_prebuilt->mysql_template[i];
9425
9426 1114787975 templ->rec_field_no = templ->clust_rec_field_no;
9427 }
9428 }
9429 156935006 }
9430
9431 /** This special handling is really to overcome the limitations of MySQL's
9432 binlogging. We need to eliminate the non-determinism that will arise in
9433 INSERT ... SELECT type of statements, since MySQL binlog only stores the
9434 min value of the autoinc interval. Once that is fixed we can get rid of
9435 the special lock handling.
9436 @return DB_SUCCESS if all OK else error code */
9437
9438 8811305 dberr_t ha_innobase::innobase_lock_autoinc(void) {
9439
1/2
✓ Branch 0 taken 8811441 times.
✗ Branch 1 not taken.
8811305 DBUG_TRACE;
9440 8811441 dberr_t error = DB_SUCCESS;
9441 8811441 long lock_mode = innobase_autoinc_lock_mode;
9442
9443
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8811441 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8811428 times.
8811441 ut_ad(!srv_read_only_mode || m_prebuilt->table->is_intrinsic());
9444
9445
6/8
✓ Branch 0 taken 8811403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8811409 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7231327 times.
✓ Branch 5 taken 1580082 times.
✓ Branch 6 taken 7231346 times.
✓ Branch 7 taken 1580057 times.
8811428 if (m_prebuilt->table->is_intrinsic() || m_prebuilt->no_autoinc_locking) {
9446 /* Intrinsic table are not shared across connection
9447 so there is no need to AUTOINC lock the table.
9448 Also we won't use AUTOINC lock if this was requested
9449 explicitly. */
9450 7231346 lock_mode = AUTOINC_NO_LOCKING;
9451 }
9452
9453
3/4
✓ Branch 0 taken 8801387 times.
✓ Branch 1 taken 1000 times.
✓ Branch 2 taken 9016 times.
✗ Branch 3 not taken.
8811403 switch (lock_mode) {
9454 8801387 case AUTOINC_NO_LOCKING:
9455 /* Acquire only the AUTOINC mutex. */
9456
1/2
✓ Branch 0 taken 8801445 times.
✗ Branch 1 not taken.
8801387 dict_table_autoinc_lock(m_prebuilt->table);
9457 8801445 break;
9458
9459 1000 case AUTOINC_NEW_STYLE_LOCKING:
9460 /* For simple (single/multi) row INSERTs, we fallback to the
9461 old style only if another transaction has already acquired
9462 the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
9463 etc. type of statement. */
9464
5/6
✓ Branch 0 taken 1000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 312 times.
✓ Branch 3 taken 688 times.
✓ Branch 4 taken 688 times.
✓ Branch 5 taken 312 times.
1312 if (thd_sql_command(m_user_thd) == SQLCOM_INSERT ||
9465
2/4
✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 312 times.
312 thd_sql_command(m_user_thd) == SQLCOM_REPLACE) {
9466 688 dict_table_t *ib_table = m_prebuilt->table;
9467
9468 /* Acquire the AUTOINC mutex. */
9469
1/2
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
688 dict_table_autoinc_lock(ib_table);
9470
9471
2/4
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 688 times.
✗ Branch 3 not taken.
688 DEBUG_SYNC_C("innobase_lock_autoinc");
9472
9473 /* We need to check that another transaction isn't
9474 already holding the AUTOINC lock on the table. */
9475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
688 if (ib_table->count_by_mode[LOCK_AUTO_INC]) {
9476 /* Release the mutex to avoid deadlocks. */
9477 dict_table_autoinc_unlock(ib_table);
9478 } else {
9479 688 break;
9480 }
9481 }
9482 /* Fall through to old style locking. */
9483 [[fallthrough]];
9484
9485 case AUTOINC_OLD_STYLE_LOCKING:
9486
2/4
✓ Branch 0 taken 9255 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9255 times.
9329 DBUG_EXECUTE_IF("die_if_autoinc_old_lock_style_used", ut_d(ut_error););
9487
1/2
✓ Branch 0 taken 9255 times.
✗ Branch 1 not taken.
9255 error = row_lock_table_autoinc_for_mysql(m_prebuilt);
9488
9489
2/2
✓ Branch 0 taken 9254 times.
✓ Branch 1 taken 1 times.
9255 if (error == DB_SUCCESS) {
9490 /* Acquire the AUTOINC mutex. */
9491
1/2
✓ Branch 0 taken 9254 times.
✗ Branch 1 not taken.
9254 dict_table_autoinc_lock(m_prebuilt->table);
9492 }
9493 9255 break;
9494
9495 default:
9496 ut_error;
9497 }
9498
9499 8811374 return error;
9500 8811388 }
9501
9502 /** Store the autoinc value in the table. The autoinc value is only set if
9503 it's greater than the existing autoinc value in the table.
9504 @return DB_SUCCESS if all went well else error code */
9505
9506 777795 dberr_t ha_innobase::innobase_set_max_autoinc(
9507 ulonglong auto_inc) /*!< in: value to store */
9508 {
9509 dberr_t error;
9510
9511 777795 error = innobase_lock_autoinc();
9512
9513
1/2
✓ Branch 0 taken 777795 times.
✗ Branch 1 not taken.
777795 if (error == DB_SUCCESS) {
9514 777795 dict_table_autoinc_update_if_greater(m_prebuilt->table, auto_inc);
9515
9516 777795 dict_table_autoinc_unlock(m_prebuilt->table);
9517 }
9518
9519 777795 return (error);
9520 }
9521
9522 /** Write Row interface optimized for intrinisc table.
9523 @param[in] record a row in MySQL format.
9524 @return 0 on success or error code */
9525 5321049 int ha_innobase::intrinsic_table_write_row(uchar *record) {
9526 dberr_t err;
9527
9528 /* No auto-increment support for intrinsic table. */
9529
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5321049 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5321049 times.
5321049 ut_ad(!(table->next_number_field && record == table->record[0]));
9530
9531
2/2
✓ Branch 0 taken 5207956 times.
✓ Branch 1 taken 113093 times.
5321049 if (m_prebuilt->mysql_template == nullptr ||
9532
2/2
✓ Branch 0 taken 24417 times.
✓ Branch 1 taken 5183539 times.
5207956 m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
9533 /* Build the template used in converting quickly between
9534 the two database formats */
9535 137510 build_template(true);
9536 }
9537
9538 5321049 err = row_insert_for_mysql((byte *)record, m_prebuilt);
9539
9540 return (
9541 5321049 convert_error_code_to_mysql(err, m_prebuilt->table->flags, m_user_thd));
9542 }
9543
9544 /** Parse out multi-value and store in a multi_value_data struct
9545 @param[in] bv JSON binary that has the mult-value
9546 @param[out] valuep store the parsed out value
9547 @param[in] fld Array Field for the data
9548 @param[in] dfield InnoDB indexed field struct
9549 @param[in] comp if this is new InnoDB row type
9550 @param[in,out] heap heap memory */
9551 26241 static void innobase_store_multi_value_low(json_binary::Value *bv,
9552 multi_value_data **valuep,
9553 Field_typed_array *fld,
9554 dfield_t *dfield, ulint comp,
9555 mem_heap_t *heap) {
9556 26241 multi_value_data *value = *valuep;
9557 byte *buf;
9558
9559 /* Even for single values, there will be an array with 1 element */
9560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26241 times.
26241 ut_ad(bv->type() == json_binary::Value::ARRAY);
9561 26241 uint32_t elements = bv->element_count();
9562
9563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26241 times.
26241 ut_ad(elements > 0);
9564
9565
2/2
✓ Branch 0 taken 25559 times.
✓ Branch 1 taken 682 times.
26241 if (value == nullptr) {
9566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25559 times.
25559 ut_ad(heap != nullptr);
9567 value =
9568 25559 static_cast<multi_value_data *>(mem_heap_zalloc(heap, sizeof(*value)));
9569 }
9570
9571
2/2
✓ Branch 0 taken 25560 times.
✓ Branch 1 taken 681 times.
26241 if (elements > value->num_alc) {
9572 25560 value->alloc(elements, false, heap);
9573 }
9574
9575 26241 buf = reinterpret_cast<byte *>(value->conv_buf);
9576
9577 26241 value->num_v = elements;
9578
9579 26241 ulint col_len = fld->key_length();
9580
9581
2/2
✓ Branch 0 taken 254809 times.
✓ Branch 1 taken 26241 times.
281050 for (uint i = 0; i < elements; i++) {
9582 254809 const byte *mysql_data = nullptr;
9583
1/2
✓ Branch 0 taken 254809 times.
✗ Branch 1 not taken.
254809 const dtype_t *dtype = dfield_get_type(dfield);
9584 254809 ulint type = dtype->mtype;
9585 int64_t val;
9586
9587
1/2
✓ Branch 0 taken 254809 times.
✗ Branch 1 not taken.
254809 json_binary::Value elt = bv->element(i);
9588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 254809 times.
254809 if (elt.type() == json_binary::Value::LITERAL_NULL) {
9589 dfield_set_data(dfield, nullptr, UNIV_SQL_NULL);
9590
2/2
✓ Branch 0 taken 253398 times.
✓ Branch 1 taken 1411 times.
254809 } else if (type == DATA_INT) {
9591 byte data[8];
9592
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 253320 times.
253398 if (elt.type() == json_binary::Value::OPAQUE) {
9593
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
156 if (elt.field_type() == MYSQL_TYPE_TIME ||
9594
3/6
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
156 elt.field_type() == MYSQL_TYPE_DATETIME ||
9595 78 elt.field_type() == MYSQL_TYPE_TIMESTAMP) {
9596 /* Newer Mysql temporal types use DATA_FIXBINARY Innodb type */
9597 ut_d(ut_error); /* purecov: inspected */
9598
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 } else if (elt.field_type() == MYSQL_TYPE_DATE) {
9599 /* Temporal data has at most 8 bytes length */
9600
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(),
9601 78 data, fld->decimals());
9602 78 mysql_data = data;
9603 } else {
9604 mysql_data = reinterpret_cast<const byte *>(elt.get_data());
9605 }
9606 } else {
9607 /* Both signed and unsigned ints are handled here. Because there is
9608 an assumption the data passed from server should be always
9609 little-endian one, so need to convert it explicitly here.
9610 @see Field_longlong::store() */
9611
2/2
✓ Branch 0 taken 253043 times.
✓ Branch 1 taken 277 times.
253320 if (fld->is_unsigned()) {
9612 253043 val = static_cast<int64_t>(elt.get_uint64());
9613 } else {
9614 277 val = elt.get_int64();
9615 }
9616 #ifdef WORDS_BIGENDIAN
9617 if (fld->table->s->db_low_byte_first) {
9618 int8store(data, val);
9619 } else
9620 #endif
9621 {
9622 253320 longlongstore(data, val);
9623 }
9624 253320 mysql_data = data;
9625 }
9626
1/2
✓ Branch 0 taken 253398 times.
✗ Branch 1 not taken.
253398 row_mysql_store_col_in_innobase_format(dfield, buf, true, mysql_data,
9627 col_len, comp, false, nullptr, 0,
9628 nullptr);
9629
4/6
✓ Branch 0 taken 1411 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1411 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 525 times.
✓ Branch 5 taken 886 times.
1411 } else if (type == DATA_CHAR || type == DATA_VARCHAR ||
9630 type == DATA_VARMYSQL) {
9631 525 mysql_data = (byte *)elt.get_data();
9632 525 col_len = (ulint)elt.get_data_length();
9633
1/2
✓ Branch 0 taken 525 times.
✗ Branch 1 not taken.
525 dfield_set_data(dfield, mysql_data, col_len);
9634
3/4
✓ Branch 0 taken 494 times.
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 494 times.
✗ Branch 3 not taken.
886 } else if (type == DATA_BINARY || type == DATA_FIXBINARY) {
9635
1/2
✓ Branch 0 taken 886 times.
✗ Branch 1 not taken.
886 if (elt.type() == json_binary::Value::OPAQUE) {
9636
3/4
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 329 times.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
886 switch (elt.field_type()) {
9637 392 case MYSQL_TYPE_VARCHAR: {
9638 392 mysql_data = reinterpret_cast<const byte *>(elt.get_data());
9639
1/2
✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
392 dfield_set_data(dfield,
9640 392 reinterpret_cast<const byte *>(elt.get_data()),
9641 392 elt.get_data_length());
9642 392 break;
9643 }
9644 329 case MYSQL_TYPE_NEWDECIMAL: {
9645 329 ut_d(my_decimal d);
9646 /* Ensure correct decimal value */
9647
2/4
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 329 times.
329 ut_ad(!Json_decimal::convert_from_binary(
9648 elt.get_data(), elt.get_data_length(), &d));
9649 /* Ensure binary is of the expected size */
9650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
329 ut_ad(Json_decimal::get_encoded_binary_len(elt.get_data_length()) ==
9651 dfield->type.len);
9652
1/2
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
329 dfield_set_data(dfield,
9653 329 Json_decimal::get_encoded_binary(elt.get_data()),
9654 329 dfield->type.len);
9655 329 break;
9656 329 }
9657 165 case MYSQL_TYPE_TIME:
9658 case MYSQL_TYPE_DATE:
9659 case MYSQL_TYPE_DATETIME:
9660 case MYSQL_TYPE_TIMESTAMP: {
9661 /* Temporal data has at most 8 bytes length */
9662
1/2
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
165 Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(),
9663 165 buf, fld->decimals());
9664
9665
1/2
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
165 dfield_set_data(dfield, buf, dfield->type.len);
9666 165 break;
9667 }
9668 default:
9669 /* Shouldn't happen */
9670 ut_d(ut_error); /* purecov: inspected */
9671 }
9672 }
9673 886 } else {
9674 /* not supported */
9675 ut_d(ut_error); /* purecov: inspected */
9676 }
9677
9678 254809 value->datap[i] = dfield->data;
9679 254809 value->data_len[i] = dfield->len;
9680 254809 buf += sizeof(uint64_t);
9681 }
9682
9683 26241 *valuep = value;
9684 26241 }
9685
9686 /** Handle the multi-value array, parse the values and store them
9687 @param[in] v JSON binary that has the mult-value
9688 @param[out] value store the parsed out value
9689 @param[in] fld array Field for the data
9690 @param[in] dfield InnoDB indexed field struct
9691 @param[in] comp if this is new InnoDB row type
9692 @param[in,out] heap heap memory
9693 @return true if values are valid and stored, otherwise false */
9694 26293 static inline bool innobase_store_multi_value(json_binary::Value &v,
9695 multi_value_data *value,
9696 Field_typed_array *fld,
9697 dfield_t *dfield, bool comp,
9698 mem_heap_t *heap) {
9699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26293 times.
26293 if (v.type() == json_binary::Value::ERROR) {
9700 /* purecov: begin inspected */
9701 my_error(ER_INVALID_JSON_BINARY_DATA, MYF(0));
9702 return (false);
9703 /* purecov: end */
9704
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 26272 times.
26293 } else if (v.type() == json_binary::Value::LITERAL_NULL) {
9705 /* When field is null, json parser creates LETERAL_NULL value.
9706 JSON NULL shouldn't get here in any other way */
9707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 ut_ad(fld->is_null());
9708 21 dfield_set_null(dfield);
9709
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 26241 times.
26272 } else if (v.element_count() == 0) {
9710 31 dfield_set_data(dfield, nullptr, UNIV_NO_INDEX_VALUE);
9711 } else {
9712 26241 innobase_store_multi_value_low(&v, &value, fld, dfield, comp, heap);
9713 26241 dfield_set_data(dfield, value, UNIV_MULTI_VALUE_ARRAY_MARKER);
9714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26241 times.
26241 ut_ad(!value->duplicate());
9715 }
9716
9717 26293 return (true);
9718 }
9719
9720 /** Parse out multi-values from a MySQL record
9721 @param[in] mysql_table MySQL table structure
9722 @param[in] f_idx field index of the multi-value column
9723 @param[in,out] dfield field structure to store parsed multi-value
9724 @param[in,out] value nullptr or the multi-value structure
9725 to store the parsed values
9726 @param[in] old_val old value if exists
9727 @param[in] comp true if InnoDB table uses compact row format
9728 @param[in,out] heap memory heap */
9729 812 void innobase_get_multi_value(const TABLE *mysql_table, ulint f_idx,
9730 dfield_t *dfield, multi_value_data *value,
9731 uint old_val, ulint comp, mem_heap_t *heap) {
9732 Field_typed_array *fld;
9733 uint length;
9734 const char *ptr;
9735
9736
2/4
✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 812 times.
812 ut_ad(dfield_check_typed(dfield));
9737
9738 812 fld = down_cast<Field_typed_array *>(mysql_table->field[f_idx]);
9739
9740
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 704 times.
812 if (old_val) {
9741
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 length = fld->data_length(old_val);
9742
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 ptr = fld->get_binary(old_val);
9743 } else {
9744
1/2
✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
704 length = fld->data_length();
9745
1/2
✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
704 ptr = fld->get_binary();
9746 }
9747
9748
1/2
✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
812 json_binary::Value v(json_binary::parse_binary(ptr, length));
9749
4/6
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 791 times.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 812 times.
812 ut_ad(v.type() == json_binary::Value::ARRAY ||
9750 v.type() == json_binary::Value::LITERAL_NULL);
9751
9752 ut_d(bool succ =)
9753
1/2
✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
812 innobase_store_multi_value(v, value, fld, dfield, comp, heap);
9754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 812 times.
812 ut_ad(succ);
9755 812 }
9756
9757 /** Stores a row in an InnoDB database, to the table specified in this
9758 handle.
9759 @return error code */
9760
9761 50929225 int ha_innobase::write_row(uchar *record) /*!< in: a row in MySQL format */
9762 {
9763 dberr_t error;
9764 50929225 int error_result = 0;
9765 50929225 bool auto_inc_used = false;
9766
9767
1/2
✓ Branch 0 taken 50930415 times.
✗ Branch 1 not taken.
50929225 DBUG_TRACE;
9768
9769 /* Increase the write count of handler */
9770
1/2
✓ Branch 0 taken 50930270 times.
✗ Branch 1 not taken.
50930415 ha_statistic_increment(&System_status_var::ha_write_count);
9771
9772
3/4
✓ Branch 0 taken 50930326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5321049 times.
✓ Branch 3 taken 45609277 times.
50930270 if (m_prebuilt->table->is_intrinsic()) {
9773
1/2
✓ Branch 0 taken 5321049 times.
✗ Branch 1 not taken.
5321049 return intrinsic_table_write_row(record);
9774 }
9775
9776
1/2
✓ Branch 0 taken 45609312 times.
✗ Branch 1 not taken.
45609277 trx_t *trx = thd_to_trx(m_user_thd);
9777
9778
1/2
✓ Branch 0 taken 45608737 times.
✗ Branch 1 not taken.
45609312 TrxInInnoDB trx_in_innodb(trx);
9779
9780
8/10
✓ Branch 0 taken 45609101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45609043 times.
✓ Branch 3 taken 58 times.
✓ Branch 4 taken 45609113 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 45609111 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 45609169 times.
45608737 if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) {
9781
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innobase_rollback(ht, m_user_thd, false);
9782
9783
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
9784 }
9785
9786 /* Validation checks before we commence write_row operation. */
9787
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 45609134 times.
45609169 if (high_level_read_only) {
9788
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
35 ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
9789 35 return HA_ERR_TABLE_READONLY;
9790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45609134 times.
45609134 } else if (m_prebuilt->trx != trx) {
9791 ib::error(ER_IB_MSG_558) << "The transaction object for the table handle is"
9792 " at "
9793 << static_cast<const void *>(m_prebuilt->trx)
9794 << ", but for the current thread it is at "
9795 << static_cast<const void *>(trx);
9796
9797 fputs("InnoDB: Dump of 200 bytes around m_prebuilt: ", stderr);
9798 ut_print_buf(stderr, ((const byte *)m_prebuilt) - 100, 200);
9799 fputs("\nInnoDB: Dump of 200 bytes around ha_data: ", stderr);
9800 ut_print_buf(stderr, ((const byte *)trx) - 100, 200);
9801 putc('\n', stderr);
9802 ut_error;
9803
3/4
✓ Branch 0 taken 45608250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2096367 times.
✓ Branch 3 taken 43511883 times.
45609134 } else if (!trx_is_started(trx)) {
9804 2096367 ++trx->will_lock;
9805 }
9806
9807 /* Handling of Auto-Increment Columns. */
9808
3/4
✓ Branch 0 taken 14579371 times.
✓ Branch 1 taken 31028879 times.
✓ Branch 2 taken 14579402 times.
✗ Branch 3 not taken.
45608250 if (table->next_number_field && record == table->record[0]) {
9809 /* Reset the error code before calling
9810 innobase_get_auto_increment(). */
9811 14579402 m_prebuilt->autoinc_error = DB_SUCCESS;
9812
9813
1/2
✓ Branch 0 taken 14579463 times.
✗ Branch 1 not taken.
14579402 error_result = update_auto_increment();
9814
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 14579452 times.
14579463 if (error_result) {
9815 /* We don't want to mask autoinc overflow errors. */
9816
9817 /* Handle the case where the AUTOINC sub-system
9818 failed during initialization. */
9819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (m_prebuilt->autoinc_error == DB_UNSUPPORTED) {
9820 error_result = ER_AUTOINC_READ_FAILED;
9821 /* Set the error message to report too. */
9822 my_error(ER_AUTOINC_READ_FAILED, MYF(0));
9823 goto func_exit;
9824
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 } else if (m_prebuilt->autoinc_error != DB_SUCCESS) {
9825 1 error = m_prebuilt->autoinc_error;
9826 1 goto report_error;
9827 }
9828
9829 /* MySQL errors are passed straight back. */
9830 10 goto func_exit;
9831 }
9832
9833 14579452 auto_inc_used = true;
9834 }
9835
9836 /* Prepare INSERT graph that will be executed for actual INSERT
9837 (This is a one time operation) */
9838
2/2
✓ Branch 0 taken 45391308 times.
✓ Branch 1 taken 216992 times.
45608300 if (m_prebuilt->mysql_template == nullptr ||
9839
2/2
✓ Branch 0 taken 749233 times.
✓ Branch 1 taken 44642075 times.
45391308 m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
9840 /* Build the template used in converting quickly between
9841 the two database formats */
9842
9843
1/2
✓ Branch 0 taken 966460 times.
✗ Branch 1 not taken.
966225 build_template(true);
9844 }
9845
9846
1/2
✓ Branch 0 taken 45608398 times.
✗ Branch 1 not taken.
45608535 error = innobase_srv_conc_enter_innodb(m_prebuilt);
9847
9848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45608398 times.
45608398 if (error != DB_SUCCESS) {
9849 goto report_error;
9850 }
9851
9852 /* Execute insert graph that will result in actual insert. */
9853
1/2
✓ Branch 0 taken 45609192 times.
✗ Branch 1 not taken.
45608398 error = row_insert_for_mysql((byte *)record, m_prebuilt);
9854
9855
3/4
✓ Branch 0 taken 40351370 times.
✓ Branch 1 taken 5258010 times.
✓ Branch 2 taken 40351409 times.
✗ Branch 3 not taken.
45609192 DEBUG_SYNC(m_user_thd, "ib_after_row_insert");
9856
9857 /* Handling of errors related to auto-increment. */
9858
2/2
✓ Branch 0 taken 14579480 times.
✓ Branch 1 taken 31029939 times.
45609419 if (auto_inc_used) {
9859 ulonglong auto_inc;
9860 ulonglong col_max_value;
9861
9862 /* Note the number of rows processed for this statement, used
9863 by get_auto_increment() to determine the number of AUTO-INC
9864 values to reserve. This is only useful for a mult-value INSERT
9865 and is a statement level counter. */
9866
2/2
✓ Branch 0 taken 13805909 times.
✓ Branch 1 taken 773571 times.
14579480 if (trx->n_autoinc_rows > 0) {
9867 13805909 --trx->n_autoinc_rows;
9868 }
9869
9870 /* We need the upper limit of the col type to check for
9871 whether we update the table autoinc counter or not. */
9872
1/2
✓ Branch 0 taken 14579480 times.
✗ Branch 1 not taken.
14579480 col_max_value = table->next_number_field->get_max_int_value();
9873
9874 /* Get the value that MySQL attempted to store in the table. */
9875
1/2
✓ Branch 0 taken 14579481 times.
✗ Branch 1 not taken.
14579480 auto_inc = table->next_number_field->val_int();
9876
9877
3/3
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 14579213 times.
✓ Branch 2 taken 18 times.
14579481 switch (error) {
9878 250 case DB_DUPLICATE_KEY:
9879
9880 /* A REPLACE command and LOAD DATA INFILE REPLACE
9881 handle a duplicate key error themselves, but we
9882 must update the autoinc counter if we are performing
9883 those statements. */
9884
9885
4/5
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 94 times.
✓ Branch 4 taken 150 times.
250 switch (thd_sql_command(m_user_thd)) {
9886 6 case SQLCOM_LOAD:
9887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!m_prebuilt->allow_duplicates()) {
9888 break;
9889 }
9890
9891 case SQLCOM_REPLACE:
9892 case SQLCOM_INSERT_SELECT:
9893 case SQLCOM_REPLACE_SELECT:
9894 100 goto set_max_autoinc;
9895
9896 150 default:
9897 150 break;
9898 }
9899
9900 150 break;
9901
9902 14579213 case DB_SUCCESS:
9903 /* If the actual value inserted is greater than
9904 the upper limit of the interval, then we try and
9905 update the table upper limit. Note: last_value
9906 will be 0 if get_auto_increment() was not called. */
9907
9908
2/2
✓ Branch 0 taken 777034 times.
✓ Branch 1 taken 13802179 times.
14579213 if (auto_inc >= m_prebuilt->autoinc_last_value) {
9909 777034 set_max_autoinc:
9910 /* This should filter out the negative
9911 values set explicitly by the user. */
9912
2/2
✓ Branch 0 taken 776955 times.
✓ Branch 1 taken 179 times.
777134 if (auto_inc <= col_max_value) {
9913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 776955 times.
776955 ut_a(m_prebuilt->autoinc_increment > 0);
9914
9915 ulonglong offset;
9916 ulonglong increment;
9917 dberr_t err;
9918
9919 776955 offset = m_prebuilt->autoinc_offset;
9920 776955 increment = m_prebuilt->autoinc_increment;
9921
9922
1/2
✓ Branch 0 taken 776955 times.
✗ Branch 1 not taken.
776955 auto_inc = innobase_next_autoinc(auto_inc, 1, increment, offset,
9923 col_max_value);
9924
9925
1/2
✓ Branch 0 taken 776955 times.
✗ Branch 1 not taken.
776955 err = innobase_set_max_autoinc(auto_inc);
9926
9927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 776955 times.
776955 if (err != DB_SUCCESS) {
9928 error = err;
9929 }
9930 }
9931 }
9932 14579313 break;
9933 18 default:
9934 18 break;
9935 }
9936 }
9937
9938
1/2
✓ Branch 0 taken 45609411 times.
✗ Branch 1 not taken.
45609420 innobase_srv_conc_exit_innodb(m_prebuilt);
9939
9940 45609412 report_error:
9941 /* Cleanup and exit. */
9942
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 45609386 times.
45609412 if (error == DB_TABLESPACE_DELETED) {
9943 26 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
9944
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 table->s->table_name.str);
9945 }
9946
9947 error_result =
9948
1/2
✓ Branch 0 taken 45609301 times.
✗ Branch 1 not taken.
45609412 convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd);
9949
9950
2/2
✓ Branch 0 taken 45609300 times.
✓ Branch 1 taken 1 times.
45609301 if (error_result == HA_FTS_INVALID_DOCID) {
9951
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(HA_FTS_INVALID_DOCID, MYF(0));
9952 }
9953
9954 45609300 func_exit:
9955
9956
1/2
✓ Branch 0 taken 45609400 times.
✗ Branch 1 not taken.
45609311 innobase_active_small();
9957
9958 45609400 return error_result;
9959 50930486 }
9960
9961 /** Fill the update vector's "old_vrow" field for those non-updated,
9962 but indexed columns. Such columns could stil present in the virtual
9963 index rec fields even if they are not updated (some other fields updated),
9964 so needs to be logged.
9965 @param[in] prebuilt InnoDB prebuilt struct
9966 @param[in,out] vfield field to filled
9967 @param[in] o_len actual column length
9968 @param[in] old_mysql_row_col MySQL old field ptr
9969 @param[in] col_pack_len MySQL field col length
9970 @param[in,out] buf buffer for a converted integer value
9971 @return used buffer ptr from row_mysql_store_col_in_innobase_format() */
9972 3637 static byte *innodb_fill_old_vcol_val(row_prebuilt_t *prebuilt,
9973 dfield_t *vfield, ulint o_len,
9974 const byte *old_mysql_row_col,
9975 ulint col_pack_len, byte *buf) {
9976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3637 times.
3637 ut_ad(dfield_check_typed(vfield));
9977
9978
2/2
✓ Branch 0 taken 3621 times.
✓ Branch 1 taken 16 times.
3637 if (o_len != UNIV_SQL_NULL) {
9979 3621 buf = row_mysql_store_col_in_innobase_format(
9980 vfield, buf, true, old_mysql_row_col, col_pack_len,
9981 3621 dict_table_is_comp(prebuilt->table), false, nullptr, 0, nullptr);
9982 } else {
9983 16 dfield_set_null(vfield);
9984 }
9985
9986 3637 return (buf);
9987 }
9988
9989 /** Parse out multi-values from both old and new MySQL records,
9990 at the meantime, calculate the difference between two records.
9991 @param[in] mysql_table MySQL table structure
9992 @param[in] field_idx field index of the multi-value column
9993 @param[in,out] old_field field structure to store the parsed old value
9994 @param[in,out] new_field field structure to store the parsed new value
9995 @param[in] old_value old value to parse
9996 @param[in] comp true if InnoDB table uses compact row format
9997 @param[in,out] heap memory heap */
9998 77 static void innobase_get_multi_value_and_diff(
9999 const TABLE *mysql_table, ulint field_idx, dfield_t *old_field,
10000 dfield_t *new_field, uint old_value, ulint comp, mem_heap_t *heap) {
10001 Field_typed_array *fld;
10002 77 const char *old_ptr = nullptr;
10003 77 const char *new_ptr = nullptr;
10004 uint old_len;
10005 uint new_len;
10006
10007 77 fld = down_cast<Field_typed_array *>(mysql_table->field[field_idx]);
10008
10009
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 old_ptr = fld->get_binary(old_value);
10010
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 old_len = fld->get_length(old_value);
10011
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 new_ptr = fld->get_binary();
10012
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 new_len = fld->get_length();
10013
10014
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 json_binary::Value old_v(json_binary::parse_binary(old_ptr, old_len));
10015
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 json_binary::Value new_v(json_binary::parse_binary(new_ptr, new_len));
10016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 ut_ad(old_v.type() == json_binary::Value::ARRAY);
10017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 ut_ad(new_v.type() == json_binary::Value::ARRAY);
10018
10019 ut_d(bool succ1 =)
10020
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 innobase_store_multi_value(old_v, nullptr, fld, old_field, comp, heap);
10021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 ut_ad(succ1);
10022 ut_d(bool succ2 =)
10023
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 innobase_store_multi_value(new_v, nullptr, fld, new_field, comp, heap);
10024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 ut_ad(succ2);
10025
10026
2/4
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
77 ut_ad(!dfield_is_null(old_field));
10027
2/4
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
77 ut_ad(!dfield_is_null(new_field));
10028 /* If no indexed value, then no need to get the difference */
10029
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 if (old_field->len == UNIV_NO_INDEX_VALUE ||
10030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 new_field->len == UNIV_NO_INDEX_VALUE) {
10031 return;
10032 }
10033
10034 /* Now old_field and new_field are having both multi-value data, in the
10035 same sequence with data in old_v and new_v, which are also sorted in
10036 ascending order. */
10037
10038 77 uint old_counter = 0;
10039 77 uint new_counter = 0;
10040 77 multi_value_data *old_mv = static_cast<multi_value_data *>(old_field->data);
10041 77 multi_value_data *new_mv = static_cast<multi_value_data *>(new_field->data);
10042
10043
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 old_mv->alloc_bitset(heap);
10044
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 new_mv->alloc_bitset(heap);
10045
10046
6/6
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 263 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 263 times.
✓ Branch 5 taken 77 times.
610 while (old_counter < old_v.element_count() &&
10047 270 new_counter < new_v.element_count()) {
10048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 263 times.
263 ut_ad(old_counter < old_mv->num_v);
10049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 263 times.
263 ut_ad(new_counter < new_mv->num_v);
10050
10051
3/6
✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 263 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 263 times.
✗ Branch 5 not taken.
263 int res = old_v.element(old_counter).eq(new_v.element(new_counter));
10052
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 181 times.
263 if (res == 0) {
10053
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 old_mv->bitset->set(old_counter++, false);
10054
1/2
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
82 new_mv->bitset->set(new_counter++, false);
10055
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 31 times.
181 } else if (res < 0) {
10056 150 ++old_counter;
10057 } else {
10058 31 ++new_counter;
10059 }
10060 }
10061 }
10062
10063 /** Checks which fields have changed in a row and stores information
10064 of them to an update vector.
10065 @return DB_SUCCESS or error code */
10066 11737974 static dberr_t calc_row_difference(
10067 upd_t *uvect, /*!< in/out: update vector */
10068 const uchar *old_row, /*!< in: old row in MySQL format */
10069 uchar *new_row, /*!< in: new row in MySQL format */
10070 TABLE *table, /*!< in: table in MySQL data
10071 dictionary */
10072 uchar *upd_buff, /*!< in: buffer to use */
10073 ulint buff_len, /*!< in: buffer length */
10074 row_prebuilt_t *prebuilt, /*!< in: InnoDB prebuilt struct */
10075 THD *thd) /*!< in: user thread */
10076 {
10077 11737974 uchar *original_upd_buff = upd_buff;
10078 Field *field;
10079 enum_field_types field_mysql_type;
10080 uint n_fields;
10081 ulint o_len;
10082 ulint n_len;
10083 ulint col_pack_len;
10084 const byte *new_mysql_row_col;
10085 const byte *old_mysql_row_col;
10086 const byte *o_ptr;
10087 const byte *n_ptr;
10088 byte *buf;
10089 upd_field_t *ufield;
10090 ulint col_type;
10091 11737974 ulint n_changed = 0;
10092 11737974 dfield_t dfield;
10093 dict_index_t *clust_index;
10094 uint i;
10095 11737980 bool changes_fts_column = false;
10096 11737980 bool changes_fts_doc_col = false;
10097
1/2
✓ Branch 0 taken 11737979 times.
✗ Branch 1 not taken.
11737980 trx_t *trx = thd_to_trx(thd);
10098 11737979 doc_id_t doc_id = FTS_NULL_DOC_ID;
10099 11737979 ulint comp = 0;
10100 11737979 ulint num_v = 0;
10101
10102
5/8
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 11737975 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11737981 times.
11737979 ut_ad(!srv_read_only_mode || prebuilt->table->is_intrinsic());
10103
10104
1/2
✓ Branch 0 taken 11737977 times.
✗ Branch 1 not taken.
11737981 comp = dict_table_is_comp(prebuilt->table);
10105
10106 11737977 n_fields = table->s->fields;
10107
1/2
✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
11737977 clust_index = prebuilt->table->first_index();
10108
10109 /* We use upd_buff to convert changed fields */
10110 11737981 buf = (byte *)upd_buff;
10111
10112
2/2
✓ Branch 0 taken 135319846 times.
✓ Branch 1 taken 11738040 times.
147057886 for (i = 0; i < n_fields; i++) {
10113 135319846 dfield.reset();
10114
10115 135319903 field = table->field[i];
10116
4/4
✓ Branch 0 taken 141191 times.
✓ Branch 1 taken 135178712 times.
✓ Branch 2 taken 82320 times.
✓ Branch 3 taken 58871 times.
135319903 bool is_virtual = innobase_is_v_fld(field);
10117
1/2
✓ Branch 0 taken 135319900 times.
✗ Branch 1 not taken.
135319903 bool is_multi_value = innobase_is_multi_value_fld(field);
10118 dict_col_t *col;
10119
10120
2/2
✓ Branch 0 taken 82320 times.
✓ Branch 1 taken 135237580 times.
135319900 if (is_virtual) {
10121 82320 col = &prebuilt->table->v_cols[num_v].m_col;
10122 } else {
10123 135237580 col = &prebuilt->table->cols[i - num_v];
10124 }
10125
10126 135319900 o_ptr = (const byte *)old_row + get_field_offset(table, field);
10127 135319901 n_ptr = (const byte *)new_row + get_field_offset(table, field);
10128
10129 /* Use new_mysql_row_col and col_pack_len save the values */
10130
10131 135319895 new_mysql_row_col = n_ptr;
10132 135319895 old_mysql_row_col = o_ptr;
10133
1/2
✓ Branch 0 taken 135319877 times.
✗ Branch 1 not taken.
135319895 col_pack_len = field->pack_length();
10134
10135 135319877 o_len = col_pack_len;
10136 135319877 n_len = col_pack_len;
10137
10138 /* We use o_ptr and n_ptr to dig up the actual data for
10139 comparison. */
10140
10141
1/2
✓ Branch 0 taken 135319873 times.
✗ Branch 1 not taken.
135319877 field_mysql_type = field->type();
10142
10143 135319873 col_type = col->mtype;
10144
10145 /* Reset the type to BLOB for multi-value field, since server may
10146 keep it as non-BLOB one. */
10147
2/2
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 135319680 times.
135319873 if (is_multi_value) {
10148 193 col_type = DATA_BLOB;
10149 }
10150
10151
3/3
✓ Branch 0 taken 28475150 times.
✓ Branch 1 taken 16442025 times.
✓ Branch 2 taken 90402698 times.
135319873 switch (col_type) {
10152 28475150 case DATA_BLOB:
10153 case DATA_POINT:
10154 case DATA_VAR_POINT:
10155 case DATA_GEOMETRY:
10156 /* Do not compress blob column while comparing */
10157
1/2
✓ Branch 0 taken 28475151 times.
✗ Branch 1 not taken.
28475150 o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len, false, nullptr, 0,
10158 &prebuilt->compress_heap);
10159
1/2
✓ Branch 0 taken 28475152 times.
✗ Branch 1 not taken.
28475151 n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len, false, nullptr, 0,
10160 &prebuilt->compress_heap);
10161
10162 28475152 break;
10163
10164 16442025 case DATA_VARCHAR:
10165 case DATA_BINARY:
10166 case DATA_VARMYSQL:
10167
1/2
✓ Branch 0 taken 16442027 times.
✗ Branch 1 not taken.
16442025 if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
10168 /* This is a >= 5.0.3 type true VARCHAR where
10169 the real payload data length is stored in
10170 1 or 2 bytes */
10171
10172 32884052 o_ptr = row_mysql_read_true_varchar(&o_len, o_ptr,
10173
2/4
✓ Branch 0 taken 16442023 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16442029 times.
✗ Branch 3 not taken.
16442027 (ulint)field->get_length_bytes());
10174
10175 16442031 n_ptr = row_mysql_read_true_varchar(&n_len, n_ptr,
10176
2/4
✓ Branch 0 taken 16442031 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16442031 times.
✗ Branch 3 not taken.
16442029 (ulint)field->get_length_bytes());
10177 }
10178
10179 16442029 break;
10180 135319879 default:;
10181 }
10182
10183
6/6
✓ Branch 0 taken 22127499 times.
✓ Branch 1 taken 113192380 times.
✓ Branch 2 taken 305 times.
✓ Branch 3 taken 22127194 times.
✓ Branch 4 taken 305 times.
✓ Branch 5 taken 135319574 times.
135320184 if (field_mysql_type == MYSQL_TYPE_LONGLONG && prebuilt->table->fts &&
10184
2/4
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 305 times.
✗ Branch 3 not taken.
305 innobase_strcasecmp(field->field_name, FTS_DOC_ID_COL_NAME) == 0) {
10185
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 doc_id = (doc_id_t)mach_read_from_n_little_endian(n_ptr, 8);
10186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
305 if (doc_id == 0) {
10187 return (DB_FTS_INVALID_DOCID);
10188 }
10189 }
10190
10191
2/2
✓ Branch 0 taken 68783151 times.
✓ Branch 1 taken 66536723 times.
135319879 if (field->is_nullable()) {
10192
3/4
✓ Branch 0 taken 68783150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33515046 times.
✓ Branch 3 taken 35268104 times.
68783151 if (field->is_null_in_record(old_row)) {
10193 33515046 o_len = UNIV_SQL_NULL;
10194 }
10195
10196
3/4
✓ Branch 0 taken 68783152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32337755 times.
✓ Branch 3 taken 36445397 times.
68783150 if (field->is_null_in_record(new_row)) {
10197 32337755 n_len = UNIV_SQL_NULL;
10198 }
10199 }
10200
10201 #ifdef UNIV_DEBUG
10202 135319875 bool online_ord_part = false;
10203 #endif
10204
10205
2/2
✓ Branch 0 taken 82320 times.
✓ Branch 1 taken 135237555 times.
135319875 if (is_virtual) {
10206 /* If the virtual column is not indexed,
10207 we shall ignore it for update */
10208
2/2
✓ Branch 0 taken 70912 times.
✓ Branch 1 taken 11408 times.
82320 if (!col->ord_part) {
10209 /* Check whether there is a table-rebuilding
10210 online ALTER TABLE in progress, and this
10211 virtual column could be newly indexed, thus
10212 it will be materialized. Then we will have
10213 to log its update.
10214 Note, we do not support online dropping virtual
10215 column while adding new index, nor with
10216 online alter column order while adding index,
10217 so the virtual column sequence must not change
10218 if it is online operation */
10219
5/6
✓ Branch 0 taken 70912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 70907 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 70911 times.
70917 if (dict_index_is_online_ddl(clust_index) &&
10220
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
5 row_log_col_is_indexed(clust_index, num_v)) {
10221 #ifdef UNIV_DEBUG
10222 1 online_ord_part = true;
10223 #endif
10224 } else {
10225 70911 num_v++;
10226 70911 continue;
10227 }
10228 }
10229
10230
2/2
✓ Branch 0 taken 225 times.
✓ Branch 1 taken 11184 times.
11409 if (!uvect->old_vrow) {
10231 225 uvect->old_vrow =
10232
1/2
✓ Branch 0 taken 225 times.
✗ Branch 1 not taken.
225 dtuple_create_with_vcol(uvect->heap, 0, prebuilt->table->n_v_cols);
10233
2/2
✓ Branch 0 taken 397 times.
✓ Branch 1 taken 225 times.
622 for (uint j = 0; j < prebuilt->table->n_v_cols; j++) {
10234
1/2
✓ Branch 0 taken 397 times.
✗ Branch 1 not taken.
397 dfield_t *field = dtuple_get_nth_v_field(uvect->old_vrow, j);
10235 /* In case a multi-value field checking read uninitialized value */
10236
1/2
✓ Branch 0 taken 397 times.
✗ Branch 1 not taken.
397 dfield_get_type(field)->prtype = 0;
10237
1/2
✓ Branch 0 taken 397 times.
✗ Branch 1 not taken.
397 dfield_set_len(field, UNIV_SQL_NULL);
10238 }
10239 }
10240
10241
2/2
✓ Branch 0 taken 8189 times.
✓ Branch 1 taken 3220 times.
11409 ulint max_field_len = DICT_MAX_FIELD_LEN_BY_FORMAT(prebuilt->table);
10242
10243 /* for virtual columns, we only materialize
10244 its index, and index field length would not
10245 exceed max_field_len. So continue if the
10246 first max_field_len bytes are matched up */
10247
4/4
✓ Branch 0 taken 11344 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 11301 times.
✓ Branch 3 taken 43 times.
11409 if (o_len != UNIV_SQL_NULL && n_len != UNIV_SQL_NULL &&
10248
3/4
✓ Branch 0 taken 5202 times.
✓ Branch 1 taken 6099 times.
✓ Branch 2 taken 5202 times.
✗ Branch 3 not taken.
11301 o_len >= max_field_len && n_len >= max_field_len &&
10249
2/2
✓ Branch 0 taken 1812 times.
✓ Branch 1 taken 3390 times.
5202 memcmp(o_ptr, n_ptr, max_field_len) == 0) {
10250
1/2
✓ Branch 0 taken 1812 times.
✗ Branch 1 not taken.
1812 dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v);
10251
2/4
✓ Branch 0 taken 1812 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1812 times.
✗ Branch 3 not taken.
1812 col->copy_type(dfield_get_type(vfield));
10252
10253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1812 times.
1812 if (is_multi_value) {
10254 innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr,
10255 static_cast<uint>(old_row - new_row), comp,
10256 uvect->per_stmt_heap);
10257 } else {
10258
1/2
✓ Branch 0 taken 1812 times.
✗ Branch 1 not taken.
1812 buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len,
10259 old_mysql_row_col, col_pack_len, buf);
10260 }
10261 1812 num_v++;
10262 1812 continue;
10263 1812 }
10264 }
10265
10266
6/6
✓ Branch 0 taken 133514021 times.
✓ Branch 1 taken 1733131 times.
✓ Branch 2 taken 101230929 times.
✓ Branch 3 taken 32283092 times.
✓ Branch 4 taken 96864362 times.
✓ Branch 5 taken 4366567 times.
135247152 if (o_len != n_len || (o_len != UNIV_SQL_NULL && o_len != 0 &&
10267
2/2
✓ Branch 0 taken 4993094 times.
✓ Branch 1 taken 91871268 times.
96864362 0 != memcmp(o_ptr, n_ptr, o_len))) {
10268 /* The field has changed */
10269 6726225 bool multi_value_calc_by_diff = false;
10270 6726225 dfield_t old_field, new_field;
10271
10272 6726259 ufield = uvect->fields + n_changed;
10273
10274 6726259 const auto old_old_v_val = ufield->old_v_val;
10275
10276 UNIV_MEM_INVALID(ufield, sizeof *ufield);
10277
10278 /* Let us use a dummy dfield to make the conversion
10279 from the MySQL column format to the InnoDB format */
10280
10281 /* If the length of new geometry object is 0, means
10282 this object is invalid geometry object, we need
10283 to block it. */
10284
5/8
✓ Branch 0 taken 711 times.
✓ Branch 1 taken 6725549 times.
✓ Branch 2 taken 711 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 711 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6726260 times.
6726259 if (DATA_GEOMETRY_MTYPE(col_type) && o_len != 0 && n_len == 0) {
10285 return (DB_CANT_CREATE_GEOMETRY_OBJECT);
10286 }
10287
10288
6/6
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 6726156 times.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 77 times.
✓ Branch 5 taken 6726183 times.
6726345 if (is_multi_value && n_len != UNIV_SQL_NULL &&
10289
3/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 8 times.
85 !field->is_null_in_record(old_row)) {
10290 /* Multi-value field and both old and new are not NULL,
10291 parse the value separately and also calculate the difference */
10292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 ut_ad(is_virtual);
10293
10294
2/4
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
77 col->copy_type(dfield_get_type(&old_field));
10295
2/4
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
77 col->copy_type(dfield_get_type(&new_field));
10296
10297 77 innobase_get_multi_value_and_diff(
10298 77 prebuilt->m_mysql_table, i, &old_field, &new_field,
10299
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 static_cast<uint>(old_row - new_row), comp, uvect->per_stmt_heap);
10300
10301 77 multi_value_calc_by_diff = true;
10302 }
10303
10304
2/2
✓ Branch 0 taken 6704418 times.
✓ Branch 1 taken 21842 times.
6726260 if (n_len != UNIV_SQL_NULL) {
10305
2/4
✓ Branch 0 taken 6704414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6704417 times.
✗ Branch 3 not taken.
6704418 col->copy_type(dfield_get_type(&dfield));
10306
10307
4/4
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 6704332 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 77 times.
6704417 if (is_multi_value && !multi_value_calc_by_diff) {
10308
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield, nullptr,
10309 0, comp, uvect->per_stmt_heap);
10310 } else {
10311
1/2
✓ Branch 0 taken 6704408 times.
✗ Branch 1 not taken.
6704402 buf = row_mysql_store_col_in_innobase_format(
10312 &dfield, (byte *)buf, true, new_mysql_row_col, col_pack_len, comp,
10313 6704409 field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED,
10314 6704409 reinterpret_cast<const byte *>(field->zip_dict_data.str),
10315 field->zip_dict_data.length, &prebuilt->compress_heap);
10316 }
10317
10318
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 6704339 times.
6704416 if (multi_value_calc_by_diff) {
10319 77 dfield_copy(&ufield->new_val, &new_field);
10320 } else {
10321 6704339 dfield_copy(&ufield->new_val, &dfield);
10322 }
10323 } else {
10324
2/4
✓ Branch 0 taken 21840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21840 times.
✗ Branch 3 not taken.
21842 col->copy_type(dfield_get_type(&ufield->new_val));
10325
1/2
✓ Branch 0 taken 21841 times.
✗ Branch 1 not taken.
21840 dfield_set_null(&ufield->new_val);
10326 }
10327
10328 6726251 ufield->exp = nullptr;
10329 6726251 ufield->orig_len = 0;
10330 6726251 ufield->mysql_field = field;
10331
10332
2/2
✓ Branch 0 taken 7683 times.
✓ Branch 1 taken 6718568 times.
6726251 if (is_virtual) {
10333
1/2
✓ Branch 0 taken 7683 times.
✗ Branch 1 not taken.
7683 dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v);
10334 7683 upd_fld_set_virtual_col(ufield);
10335 /* Set ufield->field_no to store the position of virtual column. */
10336 7683 ufield->field_no = num_v;
10337
10338
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7682 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7683 times.
7683 ut_ad(col->ord_part || online_ord_part);
10339
2/2
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 7520 times.
7683 if (old_old_v_val == nullptr) {
10340 163 ufield->old_v_val = static_cast<dfield_t *>(
10341
1/2
✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
163 mem_heap_alloc(uvect->heap, sizeof *ufield->old_v_val));
10342 } else {
10343 UNIV_MEM_VALID(ufield, sizeof *ufield);
10344 7520 ufield->old_v_val->reset();
10345 }
10346
10347
3/4
✓ Branch 0 taken 7683 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7655 times.
✓ Branch 3 taken 28 times.
7683 if (!field->is_null_in_record(old_row)) {
10348
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 7612 times.
7655 if (n_len == UNIV_SQL_NULL) {
10349
2/4
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
43 col->copy_type(dfield_get_type(&dfield));
10350 }
10351
10352
4/4
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 7559 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 77 times.
7655 if (is_multi_value && !multi_value_calc_by_diff) {
10353 19 innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield,
10354 nullptr,
10355
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 static_cast<uint>(old_row - new_row), comp,
10356 uvect->per_stmt_heap);
10357 } else {
10358
1/2
✓ Branch 0 taken 7636 times.
✗ Branch 1 not taken.
7636 buf = row_mysql_store_col_in_innobase_format(
10359 &dfield, (byte *)buf, true, old_mysql_row_col, col_pack_len,
10360 7636 comp, field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED,
10361 7636 reinterpret_cast<const byte *>(field->zip_dict_data.str),
10362 field->zip_dict_data.length, &prebuilt->compress_heap);
10363 }
10364
10365
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 7578 times.
7655 if (multi_value_calc_by_diff) {
10366 77 dfield_copy(ufield->old_v_val, &old_field);
10367 77 dfield_copy(vfield, &old_field);
10368 } else {
10369 7578 dfield_copy(ufield->old_v_val, &dfield);
10370 7578 dfield_copy(vfield, &dfield);
10371 }
10372 } else {
10373
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 col->copy_type(dfield_get_type(ufield->old_v_val));
10374
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 dfield_set_null(ufield->old_v_val);
10375
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 dfield_set_null(vfield);
10376 }
10377 7683 num_v++;
10378 } else {
10379 /* Set ufield->field_no to store the position of column in
10380 clustered index. */
10381 13437136 ufield->field_no = dict_col_get_clust_pos(
10382
1/2
✓ Branch 0 taken 6718568 times.
✗ Branch 1 not taken.
6718568 &prebuilt->table->cols[i - num_v], clust_index);
10383 #ifdef UNIV_DEBUG
10384
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 6718176 times.
6718568 if (clust_index->has_row_versions()) {
10385 396 dict_col_t *col = &prebuilt->table->cols[i - num_v];
10386 396 ufield->field_phy_pos = col->get_col_phy_pos();
10387 }
10388 #endif
10389 6718572 ufield->old_v_val = nullptr;
10390 }
10391 6726255 n_changed++;
10392
10393 /* If an FTS indexed column was changed by this
10394 UPDATE then we need to inform the FTS sub-system.
10395
10396 NOTE: Currently we re-index all FTS indexed columns
10397 even if only a subset of the FTS indexed columns
10398 have been updated. That is the reason we are
10399 checking only once here. Later we will need to
10400 note which columns have been updated and do
10401 selective processing. */
10402
3/4
✓ Branch 0 taken 1998 times.
✓ Branch 1 taken 6724257 times.
✓ Branch 2 taken 1998 times.
✗ Branch 3 not taken.
6726255 if (prebuilt->table->fts != nullptr && !is_virtual) {
10403 ulint offset;
10404 dict_table_t *innodb_table;
10405
10406 1998 innodb_table = prebuilt->table;
10407
10408
2/2
✓ Branch 0 taken 1684 times.
✓ Branch 1 taken 314 times.
1998 if (!changes_fts_column) {
10409
1/2
✓ Branch 0 taken 1684 times.
✗ Branch 1 not taken.
1684 offset = row_upd_changes_fts_column(innodb_table, ufield);
10410
10411
2/2
✓ Branch 0 taken 1367 times.
✓ Branch 1 taken 317 times.
1684 if (offset != ULINT_UNDEFINED) {
10412 1367 changes_fts_column = true;
10413 }
10414 }
10415
10416
2/2
✓ Branch 0 taken 1393 times.
✓ Branch 1 taken 605 times.
1998 if (!changes_fts_doc_col) {
10417
1/2
✓ Branch 0 taken 1393 times.
✗ Branch 1 not taken.
1393 changes_fts_doc_col = row_upd_changes_doc_id(innodb_table, ufield);
10418 }
10419 }
10420
2/2
✓ Branch 0 taken 1914 times.
✓ Branch 1 taken 128519013 times.
135247182 } else if (is_virtual) {
10421
1/2
✓ Branch 0 taken 1914 times.
✗ Branch 1 not taken.
1914 dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v);
10422
2/4
✓ Branch 0 taken 1914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1914 times.
✗ Branch 3 not taken.
1914 col->copy_type(dfield_get_type(vfield));
10423
10424
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 1825 times.
1914 if (is_multi_value) {
10425 89 innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr,
10426
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 static_cast<uint>(old_row - new_row), comp,
10427 uvect->per_stmt_heap);
10428 } else {
10429
1/2
✓ Branch 0 taken 1825 times.
✗ Branch 1 not taken.
1825 buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len,
10430 old_mysql_row_col, col_pack_len, buf);
10431 }
10432
10433
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1914 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1914 times.
1914 ut_ad(col->ord_part || online_ord_part);
10434 1914 num_v++;
10435 }
10436 }
10437
10438 /* If the update changes a column with an FTS index on it, we
10439 then add an update column node with a new document id to the
10440 other changes. We piggy back our changes on the normal UPDATE
10441 to reduce processing and IO overhead. */
10442
2/2
✓ Branch 0 taken 11736601 times.
✓ Branch 1 taken 1439 times.
11738040 if (!prebuilt->table->fts) {
10443 11736601 trx->fts_next_doc_id = 0;
10444
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1426 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
1439 } else if (changes_fts_column || changes_fts_doc_col) {
10445 1426 dict_table_t *innodb_table = prebuilt->table;
10446
10447 1426 ufield = uvect->fields + n_changed;
10448
10449
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 1062 times.
1426 if (!DICT_TF2_FLAG_IS_SET(innodb_table, DICT_TF2_FTS_HAS_DOC_ID)) {
10450 /* If Doc ID is managed by user, and if any
10451 FTS indexed column has been updated, its corresponding
10452 Doc ID must also be updated. Otherwise, return
10453 error */
10454
3/4
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 304 times.
305 if (changes_fts_column && !changes_fts_doc_col) {
10455
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 ib::warn(ER_IB_MSG_559) << "A new Doc ID must be supplied"
10456
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 " while updating FTS indexed columns.";
10457 1 return (DB_FTS_INVALID_DOCID);
10458 }
10459
10460 /* Doc ID must monotonically increase */
10461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 304 times.
304 ut_ad(innodb_table->fts->cache);
10462
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 303 times.
304 if (doc_id < prebuilt->table->fts->cache->next_doc_id) {
10463
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ib::warn(ER_IB_MSG_560) << "FTS Doc ID must be larger than "
10464
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 << innodb_table->fts->cache->next_doc_id - 1
10465
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 << " for table " << innodb_table->name;
10466
10467 1 return (DB_FTS_INVALID_DOCID);
10468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 } else if ((doc_id - prebuilt->table->fts->cache->next_doc_id) >=
10469 FTS_DOC_ID_MAX_STEP) {
10470 ib::warn(ER_IB_MSG_561)
10471 << "Doc ID " << doc_id
10472 << " is too"
10473 " big. Its difference with largest"
10474 " Doc ID used "
10475 << prebuilt->table->fts->cache->next_doc_id - 1
10476 << " cannot exceed or equal to " << FTS_DOC_ID_MAX_STEP;
10477 }
10478
10479 303 trx->fts_next_doc_id = doc_id;
10480 } else {
10481 /* If the Doc ID is a hidden column, it can't be
10482 changed by user */
10483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1062 times.
1062 ut_ad(!changes_fts_doc_col);
10484
10485 /* Doc ID column is hidden, a new Doc ID will be
10486 generated by following fts_update_doc_id() call */
10487 1062 trx->fts_next_doc_id = 0;
10488 }
10489
10490
1/2
✓ Branch 0 taken 1365 times.
✗ Branch 1 not taken.
1365 fts_update_doc_id(innodb_table, ufield, &trx->fts_next_doc_id);
10491
10492 1365 ++n_changed;
10493 1365 } else {
10494 /* We have a Doc ID column, but none of FTS indexed
10495 columns are touched, nor the Doc ID column, so set
10496 fts_next_doc_id to UINT64_UNDEFINED, which means do not
10497 update the Doc ID column */
10498 13 trx->fts_next_doc_id = UINT64_UNDEFINED;
10499 }
10500
10501 11737979 uvect->n_fields = n_changed;
10502 11737979 uvect->info_bits = 0;
10503
10504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11737973 times.
11737979 ut_a(buf <= (byte *)original_upd_buff + buff_len);
10505
10506
2/4
✓ Branch 0 taken 11737978 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11737977 times.
11737973 ut_ad(uvect->validate());
10507 11737977 return (DB_SUCCESS);
10508 }
10509
10510 /**
10511 Updates a row given as a parameter to a new value. Note that we are given
10512 whole rows, not just the fields which are updated: this incurs some
10513 overhead for CPU when we check which fields are actually updated.
10514 TODO: currently InnoDB does not prevent the 'Halloween problem':
10515 in a searched update a single row can get updated several times
10516 if its index columns are updated!
10517 @param[in] old_row Old row contents in MySQL format
10518 @param[out] new_row Updated row contents in MySQL format
10519 @return error number or 0 */
10520
10521 11737980 int ha_innobase::update_row(const uchar *old_row, uchar *new_row) {
10522 int err;
10523
10524 dberr_t error;
10525
1/2
✓ Branch 0 taken 11737986 times.
✗ Branch 1 not taken.
11737980 trx_t *trx = thd_to_trx(m_user_thd);
10526 11737986 uint64_t new_counter = 0;
10527
10528
1/2
✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
11737986 DBUG_TRACE;
10529
10530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11737985 times.
11737981 ut_a(m_prebuilt->trx == trx);
10531
10532
7/8
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11737976 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 11737980 times.
11737985 if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) {
10533
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
10534 5 return HA_ERR_TABLE_READONLY;
10535
2/4
✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11737981 times.
11737980 } else if (!trx_is_started(trx)) {
10536 ++trx->will_lock;
10537 }
10538
10539
2/2
✓ Branch 0 taken 238363 times.
✓ Branch 1 taken 11499618 times.
11737981 if (m_upd_buf == nullptr) {
10540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238363 times.
238363 ut_ad(m_upd_buf_size == 0);
10541
10542 /* Create a buffer for packing the fields of a record. Why
10543 table->reclength did not work here? Obviously, because char
10544 fields when packed actually became 1 byte longer, when we also
10545 stored the string length as the first byte. */
10546
10547 238363 m_upd_buf_size =
10548 238363 table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3;
10549
10550 238363 m_upd_buf = reinterpret_cast<uchar *>(
10551
1/2
✓ Branch 0 taken 238363 times.
✗ Branch 1 not taken.
238363 my_malloc(PSI_INSTRUMENT_ME, m_upd_buf_size, MYF(MY_WME)));
10552
10553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238363 times.
238363 if (m_upd_buf == nullptr) {
10554 m_upd_buf_size = 0;
10555 return HA_ERR_OUT_OF_MEM;
10556 }
10557 }
10558
10559
1/2
✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
11737981 ha_statistic_increment(&System_status_var::ha_update_count);
10560
10561
5/10
✓ Branch 0 taken 11654690 times.
✓ Branch 1 taken 83291 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11654690 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11737981 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 11737981 times.
11737981 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
10562 m_share->ib_table->is_corrupt))
10563 return HA_ERR_CRASHED;
10564
10565 upd_t *uvect;
10566
10567
2/2
✓ Branch 0 taken 11520845 times.
✓ Branch 1 taken 217136 times.
11737981 if (m_prebuilt->upd_node) {
10568 11520845 uvect = m_prebuilt->upd_node->update;
10569 } else {
10570
1/2
✓ Branch 0 taken 217137 times.
✗ Branch 1 not taken.
217136 uvect = row_get_prebuilt_update_vector(m_prebuilt);
10571 }
10572
10573 11737982 uvect->table = m_prebuilt->table;
10574 11737982 uvect->mysql_table = table;
10575
10576 /* Build an update vector from the modified fields in the rows
10577 (uses m_upd_buf of the handle) */
10578
10579
1/2
✓ Branch 0 taken 11737979 times.
✗ Branch 1 not taken.
11737982 error = calc_row_difference(uvect, old_row, new_row, table, m_upd_buf,
10580 m_upd_buf_size, m_prebuilt, m_user_thd);
10581
10582
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11737977 times.
11737979 if (error != DB_SUCCESS) {
10583 2 goto func_exit;
10584 }
10585
10586
6/10
✓ Branch 0 taken 11737978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11721563 times.
✓ Branch 3 taken 16415 times.
✓ Branch 4 taken 11721557 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11721557 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11737972 times.
11737977 if (!m_prebuilt->table->is_intrinsic() && TrxInInnoDB::is_aborted(trx)) {
10587 innobase_rollback(ht, m_user_thd, false);
10588
10589 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
10590 }
10591
10592 /* This is not a delete */
10593 11737972 m_prebuilt->upd_node->is_delete = false;
10594
10595
1/2
✓ Branch 0 taken 11737975 times.
✗ Branch 1 not taken.
11737972 error = innobase_srv_conc_enter_innodb(m_prebuilt);
10596
10597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11737975 times.
11737975 if (error != DB_SUCCESS) {
10598 goto func_exit;
10599 }
10600
10601
1/2
✓ Branch 0 taken 11737965 times.
✗ Branch 1 not taken.
11737975 error = row_update_for_mysql((byte *)old_row, m_prebuilt);
10602
10603
2/2
✓ Branch 0 taken 6491290 times.
✓ Branch 1 taken 5246677 times.
11737965 if (dict_table_has_autoinc_col(m_prebuilt->table)) {
10604 6491291 new_counter = row_upd_get_new_autoinc_counter(
10605
1/2
✓ Branch 0 taken 6491291 times.
✗ Branch 1 not taken.
6491290 uvect, m_prebuilt->table->autoinc_field_no);
10606 } else {
10607 5246677 new_counter = 0;
10608 }
10609
10610 /* We should handle the case if the AUTOINC counter has been
10611 updated, we want to update the counter accordingly.
10612
10613 We need to do some special AUTOINC handling for the following case:
10614
10615 INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ...
10616
10617 We need to use the AUTOINC counter that was actually used by
10618 MySQL in the UPDATE statement, which can be different from the
10619 value used in the INSERT statement. */
10620
10621
6/6
✓ Branch 0 taken 11737422 times.
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 11736639 times.
✓ Branch 3 taken 783 times.
✓ Branch 4 taken 843 times.
✓ Branch 5 taken 11737125 times.
23474607 if (error == DB_SUCCESS &&
10622 11736639 (new_counter != 0 ||
10623
3/4
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 11736564 times.
✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
11736639 (table->next_number_field && new_row == table->record[0] &&
10624
4/6
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
135 thd_sql_command(m_user_thd) == SQLCOM_INSERT &&
10625 60 m_prebuilt->allow_duplicates()))) {
10626 ulonglong auto_inc;
10627 ulonglong col_max_value;
10628
10629
2/2
✓ Branch 0 taken 783 times.
✓ Branch 1 taken 60 times.
843 if (new_counter != 0) {
10630 783 auto_inc = new_counter;
10631 } else {
10632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 ut_ad(table->next_number_field != nullptr);
10633
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 auto_inc = table->next_number_field->val_int();
10634 }
10635
10636 /* We need the upper limit of the col type to check for
10637 whether we update the table autoinc counter or not. */
10638
1/2
✓ Branch 0 taken 843 times.
✗ Branch 1 not taken.
843 col_max_value = table->found_next_number_field->get_max_int_value();
10639
10640
3/4
✓ Branch 0 taken 843 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 840 times.
✓ Branch 3 taken 3 times.
843 if (auto_inc <= col_max_value && auto_inc != 0) {
10641 ulonglong offset;
10642 ulonglong increment;
10643
10644 840 offset = m_prebuilt->autoinc_offset;
10645 840 increment = m_prebuilt->autoinc_increment;
10646
10647 auto_inc =
10648
1/2
✓ Branch 0 taken 840 times.
✗ Branch 1 not taken.
840 innobase_next_autoinc(auto_inc, 1, increment, offset, col_max_value);
10649
10650
1/2
✓ Branch 0 taken 840 times.
✗ Branch 1 not taken.
840 error = innobase_set_max_autoinc(auto_inc);
10651 }
10652 }
10653
10654
1/2
✓ Branch 0 taken 11737967 times.
✗ Branch 1 not taken.
11737968 innobase_srv_conc_exit_innodb(m_prebuilt);
10655
10656 11737969 func_exit:
10657
10658 err =
10659
1/2
✓ Branch 0 taken 11737969 times.
✗ Branch 1 not taken.
11737969 convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd);
10660
10661 /* If success and no columns were updated. */
10662
4/4
✓ Branch 0 taken 11737421 times.
✓ Branch 1 taken 548 times.
✓ Branch 2 taken 7075507 times.
✓ Branch 3 taken 4661914 times.
11737969 if (err == 0 && uvect->n_fields == 0) {
10663 /* This is the same as success, but instructs
10664 MySQL that the row is not really updated and it
10665 should not increase the count of updated rows.
10666 This is fix for http://bugs.mysql.com/29157 */
10667 7075507 err = HA_ERR_RECORD_IS_THE_SAME;
10668
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4662460 times.
4662462 } else if (err == HA_FTS_INVALID_DOCID) {
10669
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(HA_FTS_INVALID_DOCID, MYF(0));
10670 }
10671
10672 /* Tell InnoDB server that there might be work for
10673 utility threads: */
10674
10675
1/2
✓ Branch 0 taken 11737965 times.
✗ Branch 1 not taken.
11737969 innobase_active_small();
10676
10677
5/10
✓ Branch 0 taken 11654678 times.
✓ Branch 1 taken 83287 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11654678 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11737965 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 11737965 times.
11737965 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
10678 m_share->ib_table->is_corrupt))
10679 return HA_ERR_CRASHED;
10680
10681 11737965 return err;
10682 11737970 }
10683
10684 /** Deletes a row given as the parameter.
10685 @return error number or 0 */
10686
10687 8178464 int ha_innobase::delete_row(
10688 const uchar *record) /*!< in: a row in MySQL format */
10689 {
10690 dberr_t error;
10691
1/2
✓ Branch 0 taken 8178465 times.
✗ Branch 1 not taken.
8178464 trx_t *trx = thd_to_trx(m_user_thd);
10692
1/2
✓ Branch 0 taken 8178464 times.
✗ Branch 1 not taken.
8178465 TrxInInnoDB trx_in_innodb(trx);
10693
10694
1/2
✓ Branch 0 taken 8178464 times.
✗ Branch 1 not taken.
8178464 DBUG_TRACE;
10695
10696
5/10
✓ Branch 0 taken 8178464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8178464 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8178465 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8178465 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8178465 times.
8178464 if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) {
10697 innobase_rollback(ht, m_user_thd, false);
10698
10699 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
10700 }
10701
10702
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8178464 times.
8178465 ut_a(m_prebuilt->trx == trx);
10703
10704
6/8
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8178459 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 8178459 times.
8178464 if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) {
10705
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
10706 5 return HA_ERR_TABLE_READONLY;
10707
2/4
✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8178460 times.
8178459 } else if (!trx_is_started(trx)) {
10708 ++trx->will_lock;
10709 }
10710
10711
1/2
✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
8178460 ha_statistic_increment(&System_status_var::ha_delete_count);
10712
10713
5/10
✓ Branch 0 taken 8147671 times.
✓ Branch 1 taken 30789 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8147671 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8178460 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8178460 times.
8178460 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
10714 m_share->ib_table->is_corrupt))
10715 return HA_ERR_CRASHED;
10716
10717
2/2
✓ Branch 0 taken 159902 times.
✓ Branch 1 taken 8018558 times.
8178460 if (!m_prebuilt->upd_node) {
10718
1/2
✓ Branch 0 taken 159902 times.
✗ Branch 1 not taken.
159902 row_get_prebuilt_update_vector(m_prebuilt);
10719 }
10720
10721 /* This is a delete */
10722
10723 8178460 m_prebuilt->upd_node->is_delete = true;
10724
10725
1/2
✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
8178460 error = innobase_srv_conc_enter_innodb(m_prebuilt);
10726
10727
1/2
✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
8178460 if (error == DB_SUCCESS) {
10728
1/2
✓ Branch 0 taken 8178459 times.
✗ Branch 1 not taken.
8178460 error = row_update_for_mysql((byte *)record, m_prebuilt);
10729
1/2
✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
8178459 innobase_srv_conc_exit_innodb(m_prebuilt);
10730 }
10731
10732 /* Tell the InnoDB server that there might be work for
10733 utility threads: */
10734
10735
1/2
✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
8178460 innobase_active_small();
10736
10737
5/10
✓ Branch 0 taken 8147671 times.
✓ Branch 1 taken 30789 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8147671 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8178460 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8178460 times.
8178460 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
10738 m_share->ib_table->is_corrupt))
10739 return HA_ERR_CRASHED;
10740
10741
1/2
✓ Branch 0 taken 8178459 times.
✗ Branch 1 not taken.
8178460 return convert_error_code_to_mysql(error, m_prebuilt->table->flags,
10742 8178459 m_user_thd);
10743 8178464 }
10744
10745 /** Delete all rows from the table.
10746 @retval HA_ERR_WRONG_COMMAND if the table is transactional
10747 @retval 0 on success */
10748 121856 int ha_innobase::delete_all_rows() {
10749
1/2
✓ Branch 0 taken 121856 times.
✗ Branch 1 not taken.
121856 DBUG_TRACE;
10750
10751
3/4
✓ Branch 0 taken 121856 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 685 times.
✓ Branch 3 taken 121171 times.
121856 if (!m_prebuilt->table->is_intrinsic()) {
10752 /* Transactional tables should use truncate(). */
10753 685 return HA_ERR_WRONG_COMMAND;
10754 }
10755
10756
1/2
✓ Branch 0 taken 121171 times.
✗ Branch 1 not taken.
121171 row_delete_all_rows(m_prebuilt->table);
10757
10758
1/2
✓ Branch 0 taken 121171 times.
✗ Branch 1 not taken.
121171 dict_stats_update(m_prebuilt->table, DICT_STATS_EMPTY_TABLE);
10759
10760 121171 return 0;
10761 121856 }
10762
10763 /** Removes a new lock set on a row, if it was not read optimistically. This can
10764 be called after a row has been read in the processing of an UPDATE or a DELETE
10765 query, when the record doesn't match the WHERE condition. */
10766
10767 39157926 void ha_innobase::unlock_row(void) {
10768
1/2
✓ Branch 0 taken 39157926 times.
✗ Branch 1 not taken.
39157926 DBUG_TRACE;
10769
10770 /* Consistent read does not take any locks, thus there is
10771 nothing to unlock. There is no locking for intrinsic table. */
10772
10773
4/4
✓ Branch 0 taken 13198048 times.
✓ Branch 1 taken 25959878 times.
✓ Branch 2 taken 25959878 times.
✓ Branch 3 taken 13198048 times.
52355974 if (m_prebuilt->select_lock_type == LOCK_NONE ||
10774
2/4
✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
13198048 m_prebuilt->table->is_intrinsic()) {
10775 25959878 return;
10776 }
10777
10778
1/2
✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
13198048 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
10779
10780
2/4
✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
13198048 if (trx_in_innodb.is_aborted()) {
10781 return;
10782 }
10783
10784
2/4
✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
13198048 ut_ad(!m_prebuilt->table->is_intrinsic());
10785
10786 /* Ideally, this assert must be in the beginning of the function.
10787 But there are some calls to this function from the SQL layer when the
10788 transaction is in state TRX_STATE_NOT_STARTED. The check on
10789 m_prebuilt->select_lock_type above gets around this issue. */
10790
10791
3/10
✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13198048 times.
13198048 ut_ad(trx_state_eq(m_prebuilt->trx, TRX_STATE_ACTIVE) ||
10792 trx_state_eq(m_prebuilt->trx, TRX_STATE_FORCED_ROLLBACK));
10793
10794 /* The purpose of unlock_row() is to release locks held on non-matching row
10795 found during most recent row_search_mvcc() call.
10796 In higher isolation levels row_try_unlock() is a no-op, as we only set the
10797 m_prebuilt->new_rec_lock[i] when trx->releases_non_matching_rows().
10798 In lower isolation levels row_try_unlock() will remove the record locks which
10799 were newly created during the most recent row_search_mvcc() (the record locks
10800 which were merely reused, are not released as they are still needed).
10801 @see handler::was_semi_consistent_read() for great explanation of what
10802 semi-consistent read mode is all about and why we don't call row_try_unlock()
10803 in case of ROW_READ_DID_SEMI_CONSISTENT, and reset the flag instead; in short
10804 a successful semi-consistent read means we didn't acquire any lock, so don't
10805 need to unlock anything if the row doesn't match the query. */
10806
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13198009 times.
13198048 if (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT) {
10807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 ut_ad(m_prebuilt->new_rec_locks_count() == 0);
10808 39 m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
10809 }
10810
1/2
✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
13198048 m_prebuilt->try_unlock(false);
10811
3/4
✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13198048 times.
✓ Branch 3 taken 25959878 times.
39157926 }
10812
10813 /* See handler.h and row0mysql.h for docs on this function. */
10814
10815 2947353 bool ha_innobase::was_semi_consistent_read(void) {
10816 2947353 return (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT);
10817 }
10818
10819 /* See handler.h and row0mysql.h for docs on this function. */
10820
10821 418634 void ha_innobase::try_semi_consistent_read(bool yes) {
10822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 418683 times.
418634 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
10823
10824
6/6
✓ Branch 0 taken 204255 times.
✓ Branch 1 taken 214428 times.
✓ Branch 2 taken 537 times.
✓ Branch 3 taken 203715 times.
✓ Branch 4 taken 537 times.
✓ Branch 5 taken 418143 times.
418683 if (yes && m_prebuilt->trx->allow_semi_consistent()) {
10825 537 m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
10826
10827 } else {
10828 418143 m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
10829 }
10830 418680 }
10831
10832 /** Initializes a handle to use an index.
10833 @return 0 or error number */
10834 104094134 int ha_innobase::index_init(uint keynr, /*!< in: key (index) number */
10835 bool) /*!< in: 1 if result
10836 MUST be sorted
10837 according to index */
10838 {
10839
1/2
✓ Branch 0 taken 104094429 times.
✗ Branch 1 not taken.
104094134 DBUG_TRACE;
10840
10841
1/2
✓ Branch 0 taken 104094416 times.
✗ Branch 1 not taken.
208188891 return change_active_index(keynr);
10842 104094416 }
10843
10844 /** Currently does nothing.
10845 @return 0 */
10846
10847 106216059 int ha_innobase::index_end(void) {
10848
1/2
✓ Branch 0 taken 106216089 times.
✗ Branch 1 not taken.
106216059 DBUG_TRACE;
10849
10850
2/2
✓ Branch 0 taken 142748 times.
✓ Branch 1 taken 106073341 times.
106216089 if (m_prebuilt->index->last_sel_cur) {
10851
1/2
✓ Branch 0 taken 142748 times.
✗ Branch 1 not taken.
142748 m_prebuilt->index->last_sel_cur->release();
10852 }
10853
10854 106216089 active_index = MAX_KEY;
10855
10856 106216089 in_range_check_pushed_down = false;
10857
10858
1/2
✓ Branch 0 taken 106216083 times.
✗ Branch 1 not taken.
106216089 m_ds_mrr.dsmrr_close();
10859
10860 106216087 return 0;
10861 106216083 }
10862
10863 /** Converts a search mode flag understood by MySQL to a flag understood
10864 by InnoDB. */
10865 72351652 page_cur_mode_t convert_search_mode_to_innobase(ha_rkey_function find_flag) {
10866
9/12
✓ Branch 0 taken 68059845 times.
✓ Branch 1 taken 4269290 times.
✓ Branch 2 taken 15185 times.
✓ Branch 3 taken 6703 times.
✓ Branch 4 taken 192 times.
✓ Branch 5 taken 271 times.
✓ Branch 6 taken 70 times.
✓ Branch 7 taken 41 times.
✓ Branch 8 taken 65 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
72351652 switch (find_flag) {
10867 68059845 case HA_READ_KEY_EXACT:
10868 /* this does not require the index to be UNIQUE */
10869 case HA_READ_KEY_OR_NEXT:
10870 68059845 return (PAGE_CUR_GE);
10871 4269290 case HA_READ_AFTER_KEY:
10872 4269290 return (PAGE_CUR_G);
10873 15185 case HA_READ_BEFORE_KEY:
10874 15185 return (PAGE_CUR_L);
10875 6703 case HA_READ_KEY_OR_PREV:
10876 case HA_READ_PREFIX_LAST:
10877 case HA_READ_PREFIX_LAST_OR_PREV:
10878 6703 return (PAGE_CUR_LE);
10879 192 case HA_READ_MBR_CONTAIN:
10880 192 return (PAGE_CUR_CONTAIN);
10881 271 case HA_READ_MBR_INTERSECT:
10882 271 return (PAGE_CUR_INTERSECT);
10883 70 case HA_READ_MBR_WITHIN:
10884 70 return (PAGE_CUR_WITHIN);
10885 41 case HA_READ_MBR_DISJOINT:
10886 41 return (PAGE_CUR_DISJOINT);
10887 65 case HA_READ_MBR_EQUAL:
10888 65 return (PAGE_CUR_MBR_EQUAL);
10889 case HA_READ_PREFIX:
10890 return (PAGE_CUR_UNSUPP);
10891 case HA_READ_INVALID:
10892 return (PAGE_CUR_UNSUPP);
10893 /* do not use "default:" in order to produce a gcc warning:
10894 enumeration value '...' not handled in switch
10895 (if -Wswitch or -Wall is used) */
10896 }
10897
10898 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality");
10899
10900 return (PAGE_CUR_UNSUPP);
10901 }
10902
10903 #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND)
10904 79363 static bool template_new_is_valid(mysql_row_templ_t *t_new,
10905 const mysql_row_templ_t *t_saved,
10906 int n_template) {
10907 /* Percona might modify the template field `rec_field_no`, after its creation,
10908 in row0sel.cc:use_secondary_index.
10909 In order to compare the new template and the previous one, we overwrite
10910 `rec_field_no`.
10911 The new template is discarded and used just for debug purposes so we do not
10912 need to restore the previous value. */
10913
2/2
✓ Branch 0 taken 189767 times.
✓ Branch 1 taken 79363 times.
269130 for (auto i = 0; i < n_template; ++i) {
10914 189767 auto *templ_new = t_new + i;
10915 189767 const auto *templ_saved = t_saved + i;
10916 189767 templ_new->rec_field_no = templ_saved->rec_field_no;
10917 }
10918
10919 79363 return !memcmp(t_new, t_saved, n_template * sizeof(mysql_row_templ_t));
10920 }
10921 #endif
10922
10923 /*
10924 BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
10925 ---------------------------------------------------
10926 The following does not cover all the details, but explains how we determine
10927 the start of a new SQL statement, and what is associated with it.
10928
10929 For each table in the database the MySQL interpreter may have several
10930 table handle instances in use, also in a single SQL query. For each table
10931 handle instance there is an InnoDB 'm_prebuilt' struct which contains most
10932 of the InnoDB data associated with this table handle instance.
10933
10934 A) if the user has not explicitly set any MySQL table level locks:
10935
10936 1) MySQL calls ::external_lock to set an 'intention' table level lock on
10937 the table of the handle instance. There we set
10938 m_prebuilt->sql_stat_start = true. The flag sql_stat_start should be set
10939 true if we are taking this table handle instance to use in a new SQL
10940 statement issued by the user. We also increment trx->n_mysql_tables_in_use.
10941
10942 2) If m_prebuilt->sql_stat_start == true we 'pre-compile' the MySQL search
10943 instructions to m_prebuilt->template of the table handle instance in
10944 ::index_read. The template is used to save CPU time in large joins.
10945
10946 3) In row_search_for_mysql, if m_prebuilt->sql_stat_start is true, we
10947 allocate a new consistent read view for the trx if it does not yet have one,
10948 or in the case of a locking read, set an InnoDB 'intention' table level
10949 lock on the table.
10950
10951 4) We do the SELECT. MySQL may repeatedly call ::index_read for the
10952 same table handle instance, if it is a join.
10953
10954 5) When the SELECT ends, MySQL removes its intention table level locks
10955 in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
10956 (a) we execute a COMMIT there if the autocommit is on,
10957 (b) we also release possible 'SQL statement level resources' InnoDB may
10958 have for this SQL statement. The MySQL interpreter does NOT execute
10959 autocommit for pure read transactions, though it should. That is why the
10960 table handler in that case has to execute the COMMIT in ::external_lock.
10961
10962 B) If the user has explicitly set MySQL table level locks, then MySQL
10963 does NOT call ::external_lock at the start of the statement. To determine
10964 when we are at the start of a new SQL statement we at the start of
10965 ::index_read also compare the query id to the latest query id where the
10966 table handle instance was used. If it has changed, we know we are at the
10967 start of a new SQL statement. Since the query id can theoretically
10968 overwrap, we use this test only as a secondary way of determining the
10969 start of a new SQL statement. */
10970
10971 /** Positions an index cursor to the index specified in the handle. Fetches the
10972 row if any.
10973 @return 0, HA_ERR_KEY_NOT_FOUND, or error number */
10974
10975 71360326 int ha_innobase::index_read(
10976 uchar *buf, /*!< in/out: buffer for the returned
10977 row */
10978 const uchar *key_ptr, /*!< in: key value; if this is NULL
10979 we position the cursor at the
10980 start or end of index; this can
10981 also contain an InnoDB row id, in
10982 which case key_len is the InnoDB
10983 row id length; the key value can
10984 also be a prefix of a full key value,
10985 and the last column can be a prefix
10986 of a full column */
10987 uint key_len, /*!< in: key value length */
10988 enum ha_rkey_function find_flag) /*!< in: search flags from my_base.h */
10989 {
10990
1/2
✓ Branch 0 taken 71360533 times.
✗ Branch 1 not taken.
71360326 DBUG_TRACE;
10991
3/4
✓ Branch 0 taken 68608788 times.
✓ Branch 1 taken 2751745 times.
✓ Branch 2 taken 68608832 times.
✗ Branch 3 not taken.
71360533 DEBUG_SYNC_C("ha_innobase_index_read_begin");
10992
10993
2/4
✓ Branch 0 taken 71360543 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 71360555 times.
71360577 ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd));
10994
4/6
✓ Branch 0 taken 3819871 times.
✓ Branch 1 taken 67540684 times.
✓ Branch 2 taken 3819871 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 71360552 times.
71360555 ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
10995
10996
1/2
✓ Branch 0 taken 71360566 times.
✗ Branch 1 not taken.
71360552 ha_statistic_increment(&System_status_var::ha_read_key_count);
10997
10998
9/14
✓ Branch 0 taken 71360564 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 71198248 times.
✓ Branch 3 taken 162316 times.
✓ Branch 4 taken 71198255 times.
✓ Branch 5 taken 162311 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 71198255 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 71360566 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 71360566 times.
71360566 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
10999 m_share->ib_table && m_share->ib_table->is_corrupt)) {
11000 return HA_ERR_CRASHED;
11001 }
11002
11003 71360566 dict_index_t *index = m_prebuilt->index;
11004
11005
5/8
✓ Branch 0 taken 71360563 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 71360541 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 71360544 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 71360544 times.
71360566 if (index == nullptr || index->is_corrupted()) {
11006 m_prebuilt->index_usable = false;
11007 return HA_ERR_CRASHED;
11008 }
11009
11010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71360544 times.
71360544 if (!m_prebuilt->index_usable) {
11011 return index->is_corrupted() ? HA_ERR_INDEX_CORRUPT
11012 : HA_ERR_TABLE_DEF_CHANGED;
11013 }
11014
11015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71360544 times.
71360544 if (index->type & DICT_FTS) {
11016 return HA_ERR_KEY_NOT_FOUND;
11017 }
11018
11019 /* For R-Tree index, we will always place the page lock to
11020 pages being searched */
11021
3/4
✓ Branch 0 taken 71360538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 201 times.
✓ Branch 3 taken 71360337 times.
71360544 if (dict_index_is_spatial(index)) {
11022 201 ++m_prebuilt->trx->will_lock;
11023 }
11024
11025 /* Note that if the index for which the search template is built is not
11026 necessarily m_prebuilt->index, but can also be the clustered index */
11027
11028
7/8
✓ Branch 0 taken 48227603 times.
✓ Branch 1 taken 23132935 times.
✓ Branch 2 taken 48227433 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48148174 times.
✓ Branch 5 taken 79259 times.
✓ Branch 6 taken 48148242 times.
✓ Branch 7 taken 23212126 times.
71360538 if (m_prebuilt->sql_stat_start && !can_reuse_mysql_template()) {
11029
1/2
✓ Branch 0 taken 48148433 times.
✗ Branch 1 not taken.
48148242 build_template(false);
11030 }
11031
11032 #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND)
11033 /* valgrind complains about some of uninitialized bytes. skip it for now. */
11034
7/8
✓ Branch 0 taken 48227636 times.
✓ Branch 1 taken 23132923 times.
✓ Branch 2 taken 48227631 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 79363 times.
✓ Branch 5 taken 48148268 times.
✓ Branch 6 taken 79363 times.
✓ Branch 7 taken 71281191 times.
71360559 if (m_prebuilt->sql_stat_start && can_reuse_mysql_template()) {
11035 /* confirm mysql_template contents are same */
11036 79363 const auto n_template_save = m_prebuilt->n_template;
11037 79363 mysql_row_templ_t *mysql_template_save = m_prebuilt->mysql_template;
11038 79363 m_prebuilt->mysql_template = nullptr;
11039
1/2
✓ Branch 0 taken 79363 times.
✗ Branch 1 not taken.
79363 build_template(false);
11040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79363 times.
79363 ut_a(m_prebuilt->n_template == n_template_save);
11041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79363 times.
79363 ut_a(template_new_is_valid(m_prebuilt->mysql_template, mysql_template_save,
11042 n_template_save));
11043 79363 ut::free(m_prebuilt->mysql_template);
11044 79363 m_prebuilt->mysql_template = mysql_template_save;
11045 }
11046 #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
11047
11048
2/2
✓ Branch 0 taken 67540642 times.
✓ Branch 1 taken 3819912 times.
71360554 if (key_ptr != nullptr) {
11049 /* Convert the search key value to InnoDB format into
11050 m_prebuilt->search_tuple */
11051
11052 67540642 row_sel_convert_mysql_key_to_innobase(
11053 67540642 m_prebuilt->search_tuple, m_prebuilt->srch_key_val1,
11054
1/2
✓ Branch 0 taken 67540653 times.
✗ Branch 1 not taken.
67540642 m_prebuilt->srch_key_val_len, index, key_ptr, key_len);
11055
11056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67540653 times.
67540653 assert(m_prebuilt->search_tuple->n_fields > 0);
11057 } else {
11058 /* We position the cursor to the last or the first entry
11059 in the index */
11060
11061
1/2
✓ Branch 0 taken 3819870 times.
✗ Branch 1 not taken.
3819912 dtuple_set_n_fields(m_prebuilt->search_tuple, 0);
11062 }
11063
11064
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 71360495 times.
71360523 ut_ad(m_prebuilt->m_mysql_handler == this);
11065 71360495 m_prebuilt->m_stop_tuple_found = false;
11066
6/6
✓ Branch 0 taken 373733 times.
✓ Branch 1 taken 70986762 times.
✓ Branch 2 taken 343012 times.
✓ Branch 3 taken 30712 times.
✓ Branch 4 taken 343001 times.
✓ Branch 5 taken 71017485 times.
71360495 if (end_range != nullptr && m_prebuilt->is_reading_range()) {
11067 343001 row_sel_convert_mysql_key_to_innobase(
11068 343001 m_prebuilt->m_stop_tuple, m_prebuilt->srch_key_val2,
11069
1/2
✓ Branch 0 taken 343039 times.
✗ Branch 1 not taken.
343001 m_prebuilt->srch_key_val_len, index, end_range->key, end_range->length);
11070 } else {
11071
1/2
✓ Branch 0 taken 71017460 times.
✗ Branch 1 not taken.
71017485 dtuple_set_n_fields(m_prebuilt->m_stop_tuple, 0);
11072 }
11073
11074
1/2
✓ Branch 0 taken 71360361 times.
✗ Branch 1 not taken.
71360499 page_cur_mode_t mode = convert_search_mode_to_innobase(find_flag);
11075
11076 71360361 ulint match_mode = 0;
11077
11078
2/2
✓ Branch 0 taken 67419094 times.
✓ Branch 1 taken 3941267 times.
71360361 if (find_flag == HA_READ_KEY_EXACT) {
11079 67419094 match_mode = ROW_SEL_EXACT;
11080
11081
2/2
✓ Branch 0 taken 2240 times.
✓ Branch 1 taken 3939027 times.
3941267 } else if (find_flag == HA_READ_PREFIX_LAST) {
11082 2240 match_mode = ROW_SEL_EXACT_PREFIX;
11083 }
11084
11085 71360361 m_last_match_mode = (uint)match_mode;
11086
11087 dberr_t ret;
11088
11089
1/2
✓ Branch 0 taken 71360382 times.
✗ Branch 1 not taken.
71360361 if (mode != PAGE_CUR_UNSUPP) {
11090
1/2
✓ Branch 0 taken 71360359 times.
✗ Branch 1 not taken.
71360382 ret = innobase_srv_conc_enter_innodb(m_prebuilt);
11091
11092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71360359 times.
71360359 if (ret != DB_SUCCESS) {
11093 return convert_error_code_to_mysql(ret, m_prebuilt->table->flags,
11094 m_user_thd);
11095 }
11096
11097
3/4
✓ Branch 0 taken 71360467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71154385 times.
✓ Branch 3 taken 206082 times.
71360359 if (!m_prebuilt->table->is_intrinsic()) {
11098
3/4
✓ Branch 0 taken 71154393 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 71154392 times.
71154385 if (TrxInInnoDB::is_aborted(m_prebuilt->trx)) {
11099
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 innobase_rollback(ht, m_user_thd, false);
11100
11101
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11102 }
11103
11104
1/2
✓ Branch 0 taken 71154250 times.
✗ Branch 1 not taken.
71154392 m_prebuilt->ins_sel_stmt = thd_is_ins_sel_stmt(m_user_thd);
11105
11106
1/2
✓ Branch 0 taken 71154417 times.
✗ Branch 1 not taken.
71154250 ret = row_search_mvcc(buf, mode, m_prebuilt, match_mode, 0);
11107
11108 } else {
11109
1/2
✓ Branch 0 taken 206099 times.
✗ Branch 1 not taken.
206082 m_prebuilt->session = thd_to_innodb_session(m_user_thd);
11110
11111
1/2
✓ Branch 0 taken 206099 times.
✗ Branch 1 not taken.
206099 ret = row_search_no_mvcc(buf, mode, m_prebuilt, match_mode, 0);
11112 }
11113
11114
1/2
✓ Branch 0 taken 71360576 times.
✗ Branch 1 not taken.
71360516 innobase_srv_conc_exit_innodb(m_prebuilt);
11115 } else {
11116 ret = DB_UNSUPPORTED;
11117 }
11118
11119
9/14
✓ Branch 0 taken 71360547 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 71198244 times.
✓ Branch 3 taken 162303 times.
✓ Branch 4 taken 71198254 times.
✓ Branch 5 taken 162301 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 71198254 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 71360555 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 71360555 times.
71360555 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
11120 m_share->ib_table && m_share->ib_table->is_corrupt)) {
11121 return HA_ERR_CRASHED;
11122 }
11123
11124
2/4
✓ Branch 0 taken 71360570 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 71360570 times.
71360555 DBUG_EXECUTE_IF("ib_select_query_failure", ret = DB_ERROR;);
11125
11126 int error;
11127
11128
5/6
✓ Branch 0 taken 50028723 times.
✓ Branch 1 taken 19957355 times.
✓ Branch 2 taken 1373987 times.
✓ Branch 3 taken 184 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 321 times.
71360570 switch (ret) {
11129 50028723 case DB_SUCCESS:
11130 50028723 error = 0;
11131
2/2
✓ Branch 0 taken 46405572 times.
✓ Branch 1 taken 3623151 times.
50028723 if (m_prebuilt->table->is_system_table) {
11132
1/2
✓ Branch 0 taken 46405571 times.
✗ Branch 1 not taken.
46405574 srv_stats.n_system_rows_read.add(
11133
1/2
✓ Branch 0 taken 46405574 times.
✗ Branch 1 not taken.
46405572 thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1);
11134 } else {
11135
2/4
✓ Branch 0 taken 3623149 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3623147 times.
✗ Branch 3 not taken.
3623151 srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd),
11136 1);
11137 }
11138 50028718 break;
11139
11140 19957355 case DB_RECORD_NOT_FOUND:
11141 19957355 error = HA_ERR_KEY_NOT_FOUND;
11142 19957355 break;
11143
11144 1373987 case DB_END_OF_INDEX:
11145 1373987 error = HA_ERR_KEY_NOT_FOUND;
11146 1373987 break;
11147
11148 184 case DB_TABLESPACE_DELETED:
11149 184 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
11150
1/2
✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
184 ER_TABLESPACE_DISCARDED, table->s->table_name.str);
11151
11152 184 error = HA_ERR_NO_SUCH_TABLE;
11153 184 break;
11154
11155 case DB_TABLESPACE_NOT_FOUND:
11156
11157 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
11158 ER_TABLESPACE_MISSING, table->s->table_name.str);
11159
11160 error = HA_ERR_TABLESPACE_MISSING;
11161 break;
11162
11163 321 default:
11164
1/2
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
321 error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags,
11165 m_user_thd);
11166
11167 309 break;
11168 }
11169
11170 71360553 return error;
11171 71360554 }
11172
11173 /** The following functions works like index_read, but it find the last
11174 row with the current key value or prefix.
11175 @return 0, HA_ERR_KEY_NOT_FOUND, or an error code */
11176
11177 482 int ha_innobase::index_read_last(
11178 uchar *buf, /*!< out: fetched row */
11179 const uchar *key_ptr, /*!< in: key value, or a prefix of a full
11180 key value */
11181 uint key_len) /*!< in: length of the key val or prefix
11182 in bytes */
11183 {
11184 482 return (index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
11185 }
11186
11187 /** Get the index for a handle. Does not change active index.
11188 @return NULL or index instance. */
11189
11190 131854222 dict_index_t *ha_innobase::innobase_get_index(
11191 uint keynr) /*!< in: use this index; MAX_KEY means always
11192 clustered index, even if it was internally
11193 generated by InnoDB */
11194 {
11195 KEY *key;
11196 dict_index_t *index;
11197
11198
1/2
✓ Branch 0 taken 131854656 times.
✗ Branch 1 not taken.
131854222 DBUG_TRACE;
11199
11200
4/4
✓ Branch 0 taken 131401740 times.
✓ Branch 1 taken 452916 times.
✓ Branch 2 taken 131401703 times.
✓ Branch 3 taken 37 times.
131854656 if (keynr != MAX_KEY && table->s->keys > 0) {
11201 131401703 key = table->key_info + keynr;
11202
11203 131401703 index = innobase_index_lookup(m_share, keynr);
11204
11205
1/2
✓ Branch 0 taken 131401658 times.
✗ Branch 1 not taken.
131401532 if (index != nullptr) {
11206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131401600 times.
131401658 ut_a(ut_strcmp(index->name, key->name) == 0);
11207 } else {
11208 /* Can't find index with keynr in the translation
11209 table. Only print message if the index translation
11210 table exists */
11211 if (m_share->idx_trans_tbl.index_mapping != nullptr) {
11212 log_errlog(WARNING_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_WITH_KEY_NO,
11213 key ? key->name : "NULL", keynr,
11214 m_prebuilt->table->name.m_name);
11215 }
11216
11217 index = dict_table_get_index_on_name(m_prebuilt->table, key->name);
11218 }
11219 } else {
11220 452953 key = nullptr;
11221
1/2
✓ Branch 0 taken 452922 times.
✗ Branch 1 not taken.
452953 index = m_prebuilt->table->first_index();
11222 }
11223
11224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131854522 times.
131854522 if (index == nullptr) {
11225 log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_FROM_DICT_CACHE, keynr,
11226 key ? key->name : "NULL", m_prebuilt->table->name.m_name);
11227 }
11228
11229 131854661 return index;
11230 131854522 }
11231
11232 /** Changes the active index of a handle.
11233 @return 0 or error code */
11234 107422659 int ha_innobase::change_active_index(
11235 uint keynr) /*!< in: use this index; MAX_KEY means always clustered
11236 index, even if it was internally generated by
11237 InnoDB */
11238 {
11239
1/2
✓ Branch 0 taken 107422844 times.
✗ Branch 1 not taken.
107422659 DBUG_TRACE;
11240
11241
8/14
✓ Branch 0 taken 107422813 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 107422823 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 107422828 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 107422828 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 107422844 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 107422844 times.
107422844 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
11242 m_share->ib_table && m_share->ib_table->is_corrupt))
11243 return HA_ERR_CRASHED;
11244
11245
2/4
✓ Branch 0 taken 107422832 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107422757 times.
107422844 ut_ad(m_user_thd == ha_thd());
11246
2/4
✓ Branch 0 taken 107422835 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107422818 times.
107422757 ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd));
11247
11248
1/2
✓ Branch 0 taken 107422695 times.
✗ Branch 1 not taken.
107422818 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
11249
11250
8/10
✓ Branch 0 taken 107422739 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107277670 times.
✓ Branch 3 taken 145069 times.
✓ Branch 4 taken 107277695 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 107277693 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 107422762 times.
107422695 if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) {
11251
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innobase_rollback(ht, m_user_thd, false);
11252
11253
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11254 }
11255
11256 107422762 active_index = keynr;
11257
11258
1/2
✓ Branch 0 taken 107422845 times.
✗ Branch 1 not taken.
107422762 m_prebuilt->index = innobase_get_index(keynr);
11259
11260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107422845 times.
107422845 if (m_prebuilt->index == nullptr) {
11261 log_errlog(WARNING_LEVEL, ER_INNODB_ACTIVE_INDEX_CHANGE_FAILED, keynr);
11262 m_prebuilt->index_usable = false;
11263 return 1;
11264 }
11265
11266
1/2
✓ Branch 0 taken 107422724 times.
✗ Branch 1 not taken.
107422845 m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx);
11267
11268
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 107422703 times.
107422724 if (!m_prebuilt->index_usable) {
11269
3/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
21 if (m_prebuilt->index->is_corrupted()) {
11270 char table_name[MAX_FULL_NAME_LEN + 1];
11271
11272 12 innobase_format_name(table_name, sizeof table_name,
11273
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 m_prebuilt->index->table->name.m_name);
11274
11275
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (m_prebuilt->index->is_clustered()) {
11276 ut_ad(m_prebuilt->table->is_corrupted());
11277 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
11278 HA_ERR_TABLE_CORRUPT,
11279 "InnoDB: Table %s is corrupted.", table_name);
11280 return HA_ERR_TABLE_CORRUPT;
11281 } else {
11282
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
11283 HA_ERR_INDEX_CORRUPT,
11284 "InnoDB: Index %s for table %s is"
11285 " marked as corrupted",
11286 12 m_prebuilt->index->name(), table_name);
11287
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_INDEX_CORRUPT, MYF(0), m_prebuilt->index->name());
11288 12 return HA_ERR_INDEX_CORRUPT;
11289 }
11290 } else {
11291
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
11292 HA_ERR_TABLE_DEF_CHANGED,
11293 "InnoDB: insufficient history for index %u", keynr);
11294 }
11295
11296 /* The caller seems to ignore this. Thus, we must check
11297 this again in row_search_for_mysql(). */
11298 9 return HA_ERR_TABLE_DEF_CHANGED;
11299 }
11300
11301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107422702 times.
107422703 ut_a(m_prebuilt->search_tuple != nullptr);
11302
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 107422742 times.
107422702 ut_a(m_prebuilt->m_stop_tuple != nullptr);
11303
11304 /* Initialization of search_tuple is not needed for FT index
11305 since FT search returns rank only. In addition engine should
11306 be able to retrieve FTS_DOC_ID column value if necessary. */
11307
2/2
✓ Branch 0 taken 1896 times.
✓ Branch 1 taken 107420846 times.
107422742 if ((m_prebuilt->index->type & DICT_FTS)) {
11308
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 if (table->fts_doc_id_field &&
11309 134 bitmap_is_set(table->read_set,
11310
4/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 1762 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1858 times.
2030 table->fts_doc_id_field->field_index()) &&
11311
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 96 times.
134 m_prebuilt->read_just_key) {
11312 38 m_prebuilt->fts_doc_id_in_read_set = true;
11313 }
11314 } else {
11315
1/2
✓ Branch 0 taken 107420944 times.
✗ Branch 1 not taken.
107420846 m_prebuilt->init_search_tuples_types();
11316
11317 /* If it's FTS query and FTS_DOC_ID exists FTS_DOC_ID field is
11318 always added to read_set. */
11319 107420944 m_prebuilt->fts_doc_id_in_read_set =
11320
4/4
✓ Branch 0 taken 867054 times.
✓ Branch 1 taken 106553890 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 867000 times.
107420998 (m_prebuilt->read_just_key && table->fts_doc_id_field &&
11321
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 3 times.
54 m_prebuilt->in_fts_query);
11322 }
11323
11324 /* MySQL changes the active index for a handle also during some
11325 queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
11326 and then calculates the sum. Previously we played safe and used
11327 the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
11328 copying. Starting from MySQL-4.1 we use a more efficient flag here. */
11329
11330
1/2
✓ Branch 0 taken 107422831 times.
✗ Branch 1 not taken.
107422840 build_template(false);
11331
11332 107422831 return 0;
11333 107422854 }
11334
11335 /** Reads the next or previous row from a cursor, which must have previously
11336 been positioned using index_read.
11337 @return 0, HA_ERR_END_OF_FILE, or error number */
11338
11339 316467105 int ha_innobase::general_fetch(
11340 uchar *buf, /*!< in/out: buffer for next row in MySQL
11341 format */
11342 uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */
11343 uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or
11344 ROW_SEL_EXACT_PREFIX */
11345 {
11346
1/2
✓ Branch 0 taken 316467230 times.
✗ Branch 1 not taken.
316467105 DBUG_TRACE;
11347
11348
8/14
✓ Branch 0 taken 316467235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315696039 times.
✓ Branch 3 taken 771196 times.
✓ Branch 4 taken 315696050 times.
✓ Branch 5 taken 771180 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 315696050 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 316467230 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 316467230 times.
316467230 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
11349 m_share->ib_table && m_share->ib_table->is_corrupt))
11350 return HA_ERR_CRASHED;
11351
11352 316467230 const trx_t *trx = m_prebuilt->trx;
11353
11354
2/4
✓ Branch 0 taken 316466725 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 316466910 times.
316467230 ut_ad(trx == thd_to_trx(m_user_thd));
11355
11356
1/2
✓ Branch 0 taken 316466890 times.
✗ Branch 1 not taken.
316466910 bool intrinsic = m_prebuilt->table->is_intrinsic();
11357
11358
5/8
✓ Branch 0 taken 311144371 times.
✓ Branch 1 taken 5322519 times.
✓ Branch 2 taken 311144254 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 311144254 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 316466773 times.
316466890 if (!intrinsic && TrxInInnoDB::is_aborted(trx)) {
11359 innobase_rollback(ht, m_user_thd, false);
11360
11361 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11362 }
11363
11364
1/2
✓ Branch 0 taken 316466596 times.
✗ Branch 1 not taken.
316466773 auto ret = innobase_srv_conc_enter_innodb(m_prebuilt);
11365
11366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 316466596 times.
316466596 if (ret != DB_SUCCESS) {
11367 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11368 }
11369
11370
2/2
✓ Branch 0 taken 311144141 times.
✓ Branch 1 taken 5322455 times.
316466596 if (!intrinsic) {
11371
1/2
✓ Branch 0 taken 311143913 times.
✗ Branch 1 not taken.
311144141 ret = row_search_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode,
11372 direction);
11373
11374 } else {
11375
1/2
✓ Branch 0 taken 5322554 times.
✗ Branch 1 not taken.
5322455 ret = row_search_no_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode,
11376 direction);
11377 }
11378
11379
1/2
✓ Branch 0 taken 316467153 times.
✗ Branch 1 not taken.
316466467 innobase_srv_conc_exit_innodb(m_prebuilt);
11380
11381 int error;
11382
11383
4/6
✓ Branch 0 taken 295517002 times.
✓ Branch 1 taken 18509768 times.
✓ Branch 2 taken 2440238 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 145 times.
316467153 switch (ret) {
11384 295517002 case DB_SUCCESS:
11385 295517002 error = 0;
11386
2/2
✓ Branch 0 taken 228124356 times.
✓ Branch 1 taken 67392646 times.
295517002 if (m_prebuilt->table->is_system_table) {
11387
1/2
✓ Branch 0 taken 228124362 times.
✗ Branch 1 not taken.
228124359 srv_stats.n_system_rows_read.add(
11388
1/2
✓ Branch 0 taken 228124359 times.
✗ Branch 1 not taken.
228124356 thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1);
11389 } else {
11390
2/4
✓ Branch 0 taken 67392442 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67392602 times.
✗ Branch 3 not taken.
67392646 srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd),
11391 1);
11392 }
11393 295516964 break;
11394 18509768 case DB_RECORD_NOT_FOUND:
11395 18509768 error = HA_ERR_END_OF_FILE;
11396 18509768 break;
11397 2440238 case DB_END_OF_INDEX:
11398 2440238 error = HA_ERR_END_OF_FILE;
11399 2440238 break;
11400 case DB_TABLESPACE_DELETED:
11401 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
11402 table->s->table_name.str);
11403
11404 error = HA_ERR_NO_SUCH_TABLE;
11405 break;
11406 case DB_TABLESPACE_NOT_FOUND:
11407
11408 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING,
11409 table->s->table_name.str);
11410
11411 error = HA_ERR_TABLESPACE_MISSING;
11412 break;
11413 145 default:
11414
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
145 error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags,
11415 m_user_thd);
11416
11417 97 break;
11418 }
11419
11420 316467067 return error;
11421 316467067 }
11422
11423 /** Reads the next row from a cursor, which must have previously been
11424 positioned using index_read.
11425 @return 0, HA_ERR_END_OF_FILE, or error number */
11426
11427 18997859 int ha_innobase::index_next(uchar *buf) /*!< in/out: buffer for next row in
11428 MySQL format */
11429 {
11430 18997859 ha_statistic_increment(&System_status_var::ha_read_next_count);
11431
11432 18997857 return (general_fetch(buf, ROW_SEL_NEXT, 0));
11433 }
11434
11435 /** Reads the next row matching to the key value given as the parameter.
11436 @return 0, HA_ERR_END_OF_FILE, or error number */
11437
11438 109104060 int ha_innobase::index_next_same(uchar *buf, /*!< in/out: buffer for the row */
11439 const uchar *, /*!< in: key value */
11440 uint) /*!< in: key value length */
11441 {
11442 109104060 ha_statistic_increment(&System_status_var::ha_read_next_count);
11443
11444 109104066 return (general_fetch(buf, ROW_SEL_NEXT, m_last_match_mode));
11445 }
11446
11447 /** Reads the previous row from a cursor, which must have previously been
11448 positioned using index_read.
11449 @return 0, HA_ERR_END_OF_FILE, or error number */
11450
11451 19779 int ha_innobase::index_prev(
11452 uchar *buf) /*!< in/out: buffer for previous row in MySQL format */
11453 {
11454 19779 ha_statistic_increment(&System_status_var::ha_read_prev_count);
11455
11456 19779 return (general_fetch(buf, ROW_SEL_PREV, 0));
11457 }
11458
11459 /** Positions a cursor on the first record in an index and reads the
11460 corresponding row to buf.
11461 @return 0, HA_ERR_END_OF_FILE, or error code */
11462
11463 3812916 int ha_innobase::index_first(uchar *buf) /*!< in/out: buffer for the row */
11464 {
11465
1/2
✓ Branch 0 taken 3812935 times.
✗ Branch 1 not taken.
3812916 DBUG_TRACE;
11466
11467
1/2
✓ Branch 0 taken 3812936 times.
✗ Branch 1 not taken.
3812935 ha_statistic_increment(&System_status_var::ha_read_first_count);
11468
11469
1/2
✓ Branch 0 taken 3812928 times.
✗ Branch 1 not taken.
3812936 int error = index_read(buf, nullptr, 0, HA_READ_AFTER_KEY);
11470
11471 /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
11472
11473
2/2
✓ Branch 0 taken 1297703 times.
✓ Branch 1 taken 2515225 times.
3812928 if (error == HA_ERR_KEY_NOT_FOUND) {
11474 1297703 error = HA_ERR_END_OF_FILE;
11475 }
11476
11477 3812929 return error;
11478 3812928 }
11479
11480 /** Positions a cursor on the last record in an index and reads the
11481 corresponding row to buf.
11482 @return 0, HA_ERR_END_OF_FILE, or error code */
11483
11484 6934 int ha_innobase::index_last(uchar *buf) /*!< in/out: buffer for the row */
11485 {
11486
1/2
✓ Branch 0 taken 6934 times.
✗ Branch 1 not taken.
6934 DBUG_TRACE;
11487
11488
1/2
✓ Branch 0 taken 6934 times.
✗ Branch 1 not taken.
6934 ha_statistic_increment(&System_status_var::ha_read_last_count);
11489
11490
1/2
✓ Branch 0 taken 6934 times.
✗ Branch 1 not taken.
6934 int error = index_read(buf, nullptr, 0, HA_READ_BEFORE_KEY);
11491
11492 /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
11493
11494
2/2
✓ Branch 0 taken 1671 times.
✓ Branch 1 taken 5263 times.
6934 if (error == HA_ERR_KEY_NOT_FOUND) {
11495 1671 error = HA_ERR_END_OF_FILE;
11496 }
11497
11498 6934 return error;
11499 6934 }
11500
11501 198 int ha_innobase::sample_init(void *&scan_ctx, double sampling_percentage,
11502 int sampling_seed,
11503 enum_sampling_method sampling_method,
11504 const bool tablesample) {
11505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 ut_ad(table_share->is_missing_primary_key() ==
11506 (bool)m_prebuilt->clust_index_was_generated);
11507
11508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 ut_ad(sampling_percentage >= 0.0);
11509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 ut_ad(sampling_percentage <= 100.0);
11510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 ut_ad(sampling_method == enum_sampling_method::SYSTEM);
11511
11512
2/4
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
✗ Branch 3 not taken.
198 if (sampling_percentage <= 0.0 || sampling_percentage > 100.0 ||
11513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
198 sampling_method != enum_sampling_method::SYSTEM) {
11514 return 0;
11515 }
11516
11517
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 197 times.
198 if (dict_table_is_discarded(m_prebuilt->table)) {
11518
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ib_senderrf(ha_thd(), IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
11519
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 m_prebuilt->table->name.m_name);
11520
11521 1 return HA_ERR_NO_SUCH_TABLE;
11522 }
11523
11524
1/2
✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
197 int err = change_active_index(table_share->primary_key);
11525
11526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (err != 0) {
11527 return err;
11528 }
11529
11530 197 trx_t *trx{nullptr};
11531
11532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (tablesample) {
11533 update_thd();
11534
11535 trx = m_prebuilt->trx;
11536 trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE);
11537
11538 if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED) {
11539 trx_assign_read_view(trx);
11540 }
11541 }
11542
11543 /* Parallel read is not currently supported for sampling. */
11544
1/2
✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
197 size_t max_threads = Parallel_reader::available_threads(1, false);
11545
11546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (max_threads == 0) {
11547 return HA_ERR_SAMPLING_INIT_FAILED;
11548 }
11549
11550
1/2
✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
197 Histogram_sampler *sampler = ut::new_withkey<Histogram_sampler>(
11551 197 UT_NEW_THIS_FILE_PSI_KEY, max_threads, sampling_seed, sampling_percentage,
11552 sampling_method);
11553
11554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (sampler == nullptr) {
11555 Parallel_reader::release_threads(max_threads);
11556 return HA_ERR_OUT_OF_MEM;
11557 }
11558
11559 197 scan_ctx = static_cast<void *>(sampler);
11560
11561
1/2
✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
197 auto index = m_prebuilt->table->first_index();
11562
11563
1/2
✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
197 auto success = sampler->init(trx, index, m_prebuilt);
11564
11565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (!success) {
11566 return (HA_ERR_SAMPLING_INIT_FAILED);
11567 }
11568
11569
1/2
✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
197 dberr_t db_err = sampler->run();
11570
11571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (db_err != DB_SUCCESS) {
11572 return (convert_error_code_to_mysql(db_err, 0, ha_thd()));
11573 }
11574
11575 197 return (0);
11576 }
11577
11578 40583 int ha_innobase::sample_next(void *scan_ctx, uchar *buf) {
11579 40583 dberr_t err = DB_SUCCESS;
11580
11581 40583 Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx);
11582
11583 40583 sampler->set(buf);
11584
11585 /** Buffer rows one by one */
11586 40583 err = sampler->buffer_next();
11587
11588
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 40389 times.
40583 if (err == DB_END_OF_INDEX) {
11589 194 return HA_ERR_END_OF_FILE;
11590 }
11591
11592 40389 return (convert_error_code_to_mysql(err, 0, ha_thd()));
11593 }
11594
11595 197 int ha_innobase::sample_end(void *scan_ctx) {
11596 197 Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx);
11597
11598 197 ut::delete_(sampler);
11599
11600 197 return 0;
11601 }
11602
11603 416932 int ha_innobase::read_range_first(const key_range *start_key,
11604 const key_range *end_key, bool eq_range_arg,
11605 bool sorted) {
11606
1/2
✓ Branch 0 taken 416974 times.
✗ Branch 1 not taken.
416932 auto guard = m_prebuilt->get_is_reading_range_guard();
11607
1/2
✓ Branch 0 taken 417023 times.
✗ Branch 1 not taken.
833997 return handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
11608 417023 }
11609
11610 3040875 int ha_innobase::read_range_next() {
11611
1/2
✓ Branch 0 taken 3040875 times.
✗ Branch 1 not taken.
3040875 auto guard = m_prebuilt->get_is_reading_range_guard();
11612
1/2
✓ Branch 0 taken 3040876 times.
✗ Branch 1 not taken.
6081751 return (handler::read_range_next());
11613 3040876 }
11614
11615 /** Initialize a table scan.
11616 @param[in] scan whether this is a second call to rnd_init()
11617 without rnd_end() in between
11618 @return 0 or error number */
11619 3328201 int ha_innobase::rnd_init(bool scan) {
11620
1/2
✓ Branch 0 taken 3328208 times.
✗ Branch 1 not taken.
3328201 DBUG_TRACE;
11621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3328204 times.
3328208 assert(table_share->is_missing_primary_key() ==
11622 (bool)m_prebuilt->clust_index_was_generated);
11623
11624
1/2
✓ Branch 0 taken 3328204 times.
✗ Branch 1 not taken.
3328204 int err = change_active_index(table_share->primary_key);
11625
11626 /* Don't use semi-consistent read in random row reads (by position).
11627 This means we must disable semi_consistent_read if scan is false */
11628
11629
2/2
✓ Branch 0 taken 215236 times.
✓ Branch 1 taken 3112968 times.
3328204 if (!scan) {
11630 215236 m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
11631 }
11632
11633 3328204 m_start_of_scan = true;
11634 3328208 return err;
11635 3328204 }
11636
11637 /** Ends a table scan.
11638 @return 0 or error number */
11639
11640 1985664 int ha_innobase::rnd_end(void) { return (index_end()); }
11641
11642 /** Reads the next row in a table scan (also used to read the FIRST row
11643 in a table scan).
11644 @return 0, HA_ERR_END_OF_FILE, or error number */
11645
11646 190783849 int ha_innobase::rnd_next(uchar *buf) /*!< in/out: returns the row in this
11647 buffer, in MySQL format */
11648 {
11649 int error;
11650
11651
1/2
✓ Branch 0 taken 190784516 times.
✗ Branch 1 not taken.
190783849 DBUG_TRACE;
11652
11653
1/2
✓ Branch 0 taken 190784536 times.
✗ Branch 1 not taken.
190784516 ha_statistic_increment(&System_status_var::ha_read_rnd_next_count);
11654
11655
2/2
✓ Branch 0 taken 3112961 times.
✓ Branch 1 taken 187671575 times.
190784536 if (m_start_of_scan) {
11656
1/2
✓ Branch 0 taken 3112958 times.
✗ Branch 1 not taken.
3112961 error = index_first(buf);
11657
11658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3112958 times.
3112958 if (error == HA_ERR_KEY_NOT_FOUND) {
11659 error = HA_ERR_END_OF_FILE;
11660 }
11661
11662 3112958 m_start_of_scan = false;
11663 } else {
11664
1/2
✓ Branch 0 taken 187670946 times.
✗ Branch 1 not taken.
187671575 error = general_fetch(buf, ROW_SEL_NEXT, 0);
11665 }
11666
11667 190784658 return error;
11668 190783904 }
11669
11670 /** Fetches a row from the table based on a row reference.
11671 @return 0, HA_ERR_KEY_NOT_FOUND, or error code */
11672
11673 957701 int ha_innobase::rnd_pos(
11674 uchar *buf, /*!< in/out: buffer for the row */
11675 uchar *pos) /*!< in: primary key value of the row in the
11676 MySQL format, or the row id if the clustered
11677 index was internally generated by InnoDB; the
11678 length of data in pos has to be ref_length */
11679 {
11680
1/2
✓ Branch 0 taken 957705 times.
✗ Branch 1 not taken.
957701 DBUG_TRACE;
11681
1/2
✓ Branch 0 taken 957705 times.
✗ Branch 1 not taken.
957705 DBUG_DUMP("key", pos, ref_length);
11682
11683
1/2
✓ Branch 0 taken 957704 times.
✗ Branch 1 not taken.
957705 ha_statistic_increment(&System_status_var::ha_read_rnd_count);
11684
11685
3/6
✓ Branch 0 taken 957703 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 957705 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 957704 times.
957704 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
11686
11687 /* Note that we assume the length of the row reference is fixed
11688 for the table, and it is == ref_length */
11689
11690
1/2
✓ Branch 0 taken 957705 times.
✗ Branch 1 not taken.
957704 int error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
11691
11692
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 957626 times.
957705 if (error != 0) {
11693
3/8
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 79 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
79 DBUG_PRINT("error", ("Got error: %d", error));
11694 } else {
11695 957626 m_start_of_scan = false;
11696 }
11697
11698 957705 return error;
11699 957705 }
11700
11701 /** Initialize FT index scan
11702 @return 0 or error number */
11703
11704 1916 int ha_innobase::ft_init() {
11705
1/2
✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
1916 DBUG_TRACE;
11706
11707
2/4
✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1916 times.
✗ Branch 3 not taken.
1916 trx_t *trx = check_trx_exists(ha_thd());
11708
11709 /* FTS queries are not treated as autocommit non-locking selects.
11710 This is because the FTS implementation can acquire locks behind
11711 the scenes. This has not been verified but it is safer to treat
11712 them as regular read only transactions for now. */
11713
11714
3/4
✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1715 times.
✓ Branch 3 taken 201 times.
1916 if (!trx_is_started(trx)) {
11715 1715 ++trx->will_lock;
11716 }
11717
11718
1/2
✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
3832 return rnd_init(false);
11719 1916 }
11720
11721 /** Initialize FT index scan
11722 @return FT_INFO structure if successful or NULL */
11723
11724 2290 FT_INFO *ha_innobase::ft_init_ext(uint flags, /* in: */
11725 uint keynr, /* in: */
11726 String *key) /* in: */
11727 {
11728 2290 NEW_FT_INFO *fts_hdl = nullptr;
11729 dict_index_t *index;
11730 fts_result_t *result;
11731 char buf_tmp[8192];
11732 ulint buf_tmp_used;
11733 uint num_errors;
11734 2290 ulint query_len = key->length();
11735 2290 const CHARSET_INFO *char_set = key->charset();
11736 2290 const char *query = key->ptr();
11737
11738
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2252 times.
2290 if (fts_enable_diag_print) {
11739 {
11740
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 ib::info out(ER_IB_MSG_1220);
11741
3/6
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
38 out << "keynr=" << keynr << ", '";
11742
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 out.write(key->ptr(), key->length());
11743 38 }
11744
11745
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6 times.
38 if (flags & FT_BOOL) {
11746
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 ib::info(ER_IB_MSG_562) << "BOOL search";
11747 } else {
11748
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 ib::info(ER_IB_MSG_563) << "NL search";
11749 }
11750 }
11751
11752 /* FIXME: utf32 and utf16 are not compatible with some
11753 string function used. So to convert them to uft8 before
11754 we proceed. */
11755
1/2
✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
2290 if (strcmp(char_set->csname, "utf32") == 0 ||
11756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2290 times.
2290 strcmp(char_set->csname, "utf16") == 0) {
11757 buf_tmp_used = innobase_convert_string(
11758 buf_tmp, sizeof(buf_tmp) - 1, &my_charset_utf8_general_ci, query,
11759 query_len, (CHARSET_INFO *)char_set, &num_errors);
11760
11761 buf_tmp[buf_tmp_used] = 0;
11762 query = buf_tmp;
11763 query_len = buf_tmp_used;
11764 }
11765
11766 2290 trx_t *trx = m_prebuilt->trx;
11767
11768
1/2
✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
2290 TrxInInnoDB trx_in_innodb(trx);
11769
11770
2/4
✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2290 times.
2290 if (trx_in_innodb.is_aborted()) {
11771 innobase_rollback(ht, m_user_thd, false);
11772
11773 int err;
11774 err = convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
11775
11776 my_error(err, MYF(0));
11777
11778 return (nullptr);
11779 }
11780
11781 /* FTS queries are not treated as autocommit non-locking selects.
11782 This is because the FTS implementation can acquire locks behind
11783 the scenes. This has not been verified but it is safer to treat
11784 them as regular read only transactions for now. */
11785
11786
3/4
✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2118 times.
✓ Branch 3 taken 172 times.
2290 if (!trx_is_started(trx)) {
11787 2118 ++trx->will_lock;
11788 }
11789
11790 2290 dict_table_t *ft_table = m_prebuilt->table;
11791
11792 /* Table does not have an FTS index */
11793
3/6
✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2290 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2290 times.
2290 if (!ft_table->fts || ib_vector_is_empty(ft_table->fts->indexes)) {
11794 my_error(ER_TABLE_HAS_NO_FT, MYF(0));
11795 return (nullptr);
11796 }
11797
11798 /* If tablespace is discarded, we should return here */
11799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2290 times.
2290 if (dict_table_is_discarded(ft_table)) {
11800 my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->db.str,
11801 table->s->table_name.str);
11802 return (nullptr);
11803 }
11804
11805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2290 times.
2290 if (keynr == NO_SUCH_KEY) {
11806 /* FIXME: Investigate the NO_SUCH_KEY usage */
11807 index = reinterpret_cast<dict_index_t *>(
11808 ib_vector_getp(ft_table->fts->indexes, 0));
11809 } else {
11810
1/2
✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
2290 index = innobase_get_index(keynr);
11811 }
11812
11813
3/4
✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2289 times.
2290 if (index == nullptr || index->type != DICT_FTS) {
11814
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_TABLE_HAS_NO_FT, MYF(0));
11815 1 return (nullptr);
11816 }
11817
11818
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 2235 times.
2289 if (!(ft_table->fts->fts_status & ADDED_TABLE_SYNCED)) {
11819
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 fts_init_index(ft_table, false);
11820
11821 54 ft_table->fts->fts_status |= ADDED_TABLE_SYNCED;
11822 }
11823
11824 2289 const byte *q = reinterpret_cast<const byte *>(const_cast<char *>(query));
11825
11826 4578 dberr_t error = fts_query(trx, index, flags, q, query_len, &result,
11827
1/2
✓ Branch 0 taken 2289 times.
✗ Branch 1 not taken.
2289 m_prebuilt->m_fts_limit);
11828
11829
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2283 times.
2289 if (error != DB_SUCCESS) {
11830
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 my_error(convert_error_code_to_mysql(error, 0, nullptr), MYF(0));
11831 6 return (nullptr);
11832 }
11833
11834 /* Allocate FTS handler, and instantiate it before return */
11835 fts_hdl = reinterpret_cast<NEW_FT_INFO *>(
11836
1/2
✓ Branch 0 taken 2283 times.
✗ Branch 1 not taken.
2283 my_malloc(PSI_INSTRUMENT_ME, sizeof(NEW_FT_INFO), MYF(0)));
11837
11838 2283 fts_hdl->please = const_cast<_ft_vft *>(&ft_vft_result);
11839 2283 fts_hdl->could_you = const_cast<_ft_vft_ext *>(&ft_vft_ext_result);
11840 2283 fts_hdl->ft_prebuilt = m_prebuilt;
11841 2283 fts_hdl->ft_result = result;
11842
11843 /* FIXME: Re-evaluate the condition when Bug 14469540 is resolved */
11844 2283 m_prebuilt->in_fts_query = true;
11845
11846 2283 return (reinterpret_cast<FT_INFO *>(fts_hdl));
11847 2290 }
11848
11849 /** Initialize FT index scan
11850 @return FT_INFO structure if successful or NULL */
11851
11852 2290 FT_INFO *ha_innobase::ft_init_ext_with_hints(uint keynr, /* in: key num */
11853 String *key, /* in: key */
11854 Ft_hints *hints) /* in: hints */
11855 {
11856 /* TODO Implement function properly working with FT hint. */
11857
2/2
✓ Branch 0 taken 1273 times.
✓ Branch 1 taken 1017 times.
2290 if (hints->get_flags() & FT_NO_RANKING) {
11858 1273 m_prebuilt->m_fts_limit = hints->get_limit();
11859 } else {
11860 1017 m_prebuilt->m_fts_limit = ULONG_UNDEFINED;
11861 }
11862
11863 2290 return (ft_init_ext(hints->get_flags(), keynr, key));
11864 }
11865
11866 /** Set up search tuple for a query through FTS_DOC_ID_INDEX on
11867 supplied Doc ID. This is used by MySQL to retrieve the documents
11868 once the search result (Doc IDs) is available */
11869 2686 static void innobase_fts_create_doc_id_key(
11870 dtuple_t *tuple, /* in/out: m_prebuilt->search_tuple */
11871 const dict_index_t *index, /* in: index (FTS_DOC_ID_INDEX) */
11872 doc_id_t *doc_id) /* in/out: doc id to search, value
11873 could be changed to storage format
11874 used for search. */
11875 {
11876 doc_id_t temp_doc_id;
11877
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 dfield_t *dfield = dtuple_get_nth_field(tuple, 0);
11878
11879
2/4
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2686 times.
2686 ut_a(dict_index_get_n_unique(index) == 1);
11880
11881
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 dtuple_set_n_fields(tuple, index->n_fields);
11882
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 dict_index_copy_types(tuple, index, index->n_fields);
11883
11884 #ifdef UNIV_DEBUG
11885 /* The unique Doc ID field should be an eight-bytes integer */
11886
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 dict_field_t *field = index->get_field(0);
11887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
2686 ut_a(field->col->mtype == DATA_INT);
11888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
2686 ut_ad(sizeof(*doc_id) == field->fixed_len);
11889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
2686 ut_ad(!strcmp(index->name, FTS_DOC_ID_INDEX_NAME));
11890 #endif /* UNIV_DEBUG */
11891
11892 /* Convert to storage byte order */
11893
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 mach_write_to_8(reinterpret_cast<byte *>(&temp_doc_id), *doc_id);
11894 2686 *doc_id = temp_doc_id;
11895
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 dfield_set_data(dfield, doc_id, sizeof(*doc_id));
11896
11897
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 dtuple_set_n_fields_cmp(tuple, 1);
11898
11899
2/2
✓ Branch 0 taken 2407 times.
✓ Branch 1 taken 2686 times.
5093 for (ulint i = 1; i < index->n_fields; i++) {
11900
1/2
✓ Branch 0 taken 2407 times.
✗ Branch 1 not taken.
2407 dfield = dtuple_get_nth_field(tuple, i);
11901
1/2
✓ Branch 0 taken 2407 times.
✗ Branch 1 not taken.
2407 dfield_set_null(dfield);
11902 }
11903 2686 }
11904
11905 /** Fetch next result from the FT result set
11906 @return error code */
11907
11908 4678 int ha_innobase::ft_read(uchar *buf) /*!< in/out: buf contain result row */
11909 {
11910
1/2
✓ Branch 0 taken 4678 times.
✗ Branch 1 not taken.
4678 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
11911
11912
2/4
✓ Branch 0 taken 4678 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4678 times.
4678 if (trx_in_innodb.is_aborted()) {
11913 innobase_rollback(ht, m_user_thd, false);
11914
11915 return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd));
11916 }
11917
11918 row_prebuilt_t *ft_prebuilt;
11919
11920 4678 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_prebuilt;
11921
11922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4678 times.
4678 ut_a(ft_prebuilt == m_prebuilt);
11923
11924 fts_result_t *result;
11925
11926 4678 result = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_result;
11927
11928
2/2
✓ Branch 0 taken 1914 times.
✓ Branch 1 taken 2764 times.
4678 if (result->current == nullptr) {
11929 /* This is the case where the FTS query did not
11930 contain and matching documents. */
11931
2/2
✓ Branch 0 taken 1431 times.
✓ Branch 1 taken 483 times.
1914 if (result->rankings_by_id != nullptr) {
11932 /* Now that we have the complete result, we
11933 need to sort the document ids on their rank
11934 calculation. */
11935
11936
1/2
✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
1431 fts_query_sort_result_on_rank(result);
11937
11938 1431 result->current =
11939
1/2
✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
1431 const_cast<ib_rbt_node_t *>(rbt_first(result->rankings_by_rank));
11940 } else {
11941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
483 ut_a(result->current == nullptr);
11942 }
11943 } else {
11944 2764 result->current = const_cast<ib_rbt_node_t *>(
11945
1/2
✓ Branch 0 taken 2764 times.
✗ Branch 1 not taken.
2764 rbt_next(result->rankings_by_rank, result->current));
11946 }
11947
11948 4678 next_record:
11949
11950
2/2
✓ Branch 0 taken 2820 times.
✓ Branch 1 taken 1862 times.
4682 if (result->current != nullptr) {
11951 doc_id_t search_doc_id;
11952 2820 dtuple_t *tuple = m_prebuilt->search_tuple;
11953
11954 /* If we only need information from result we can return
11955 without fetching the table row */
11956
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 2686 times.
2820 if (ft_prebuilt->read_just_key) {
11957 134 const fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
11958 134 m_prebuilt->fts_doc_id = ranking->doc_id;
11959
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 if (m_prebuilt->fts_doc_id_in_read_set) {
11960
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 innobase_fts_store_docid(table, ranking->doc_id);
11961 }
11962 2816 return (0);
11963 }
11964
11965 dict_index_t *index;
11966
11967 2686 index = m_prebuilt->table->fts_doc_id_index;
11968
11969 /* Must find the index */
11970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
2686 ut_a(index != nullptr);
11971
11972 /* Switch to the FTS doc id index */
11973 2686 m_prebuilt->index = index;
11974
11975 2686 fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
11976
11977 2686 search_doc_id = ranking->doc_id;
11978
11979 /* We pass a pointer of search_doc_id because it will be
11980 converted to storage byte order used in the search
11981 tuple. */
11982
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 innobase_fts_create_doc_id_key(tuple, index, &search_doc_id);
11983
11984
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 auto ret = innobase_srv_conc_enter_innodb(m_prebuilt);
11985
11986
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 if (ret == DB_SUCCESS) {
11987
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 ret = row_search_for_mysql((byte *)buf, PAGE_CUR_GE, m_prebuilt,
11988 ROW_SEL_EXACT, 0);
11989
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 innobase_srv_conc_exit_innodb(m_prebuilt);
11990 }
11991
11992 int error;
11993
11994
6/14
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2686 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2686 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2686 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2686 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2686 times.
2686 if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share &&
11995 m_share->ib_table && m_share->ib_table->is_corrupt)) {
11996 return (HA_ERR_CRASHED);
11997 }
11998
11999
2/6
✓ Branch 0 taken 2670 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2686 switch (ret) {
12000 2670 case DB_SUCCESS:
12001 2670 error = 0;
12002 2670 break;
12003 16 case DB_RECORD_NOT_FOUND:
12004 16 result->current = const_cast<ib_rbt_node_t *>(
12005
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 rbt_next(result->rankings_by_rank, result->current));
12006
12007
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 if (!result->current) {
12008 /* exhaust the result set, should return
12009 HA_ERR_END_OF_FILE just like
12010 ha_innobase::general_fetch() and/or
12011 ha_innobase::index_first() etc. */
12012 12 error = HA_ERR_END_OF_FILE;
12013 } else {
12014 4 goto next_record;
12015 }
12016 12 break;
12017 case DB_END_OF_INDEX:
12018 error = HA_ERR_END_OF_FILE;
12019 break;
12020 case DB_TABLESPACE_DELETED:
12021
12022 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
12023 ER_TABLESPACE_DISCARDED, table->s->table_name.str);
12024
12025 error = HA_ERR_NO_SUCH_TABLE;
12026 break;
12027 case DB_TABLESPACE_NOT_FOUND:
12028
12029 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
12030 ER_TABLESPACE_MISSING, table->s->table_name.str);
12031
12032 error = HA_ERR_TABLESPACE_MISSING;
12033 break;
12034 default:
12035 error = convert_error_code_to_mysql(ret, 0, m_user_thd);
12036
12037 break;
12038 }
12039
12040 2682 return (error);
12041 }
12042
12043 1862 return (HA_ERR_END_OF_FILE);
12044 4678 }
12045
12046 /*************************************************************************
12047 */
12048
12049 void ha_innobase::ft_end() {
12050 ib::info(ER_IB_MSG_564) << "ft_end()";
12051
12052 rnd_end();
12053 }
12054
12055 /**
12056 Store a reference to the current row to 'ref' field of the handle.
12057 Note that in the case where we have generated the clustered index for the
12058 table, the function parameter is illogical: we MUST ASSUME that 'record'
12059 is the current 'position' of the handle, because if row ref is actually
12060 the row id internally generated in InnoDB, then 'record' does not contain
12061 it. We just guess that the row id must be for the record where the handle
12062 was positioned the last time.
12063 @param[in] record row in MySQL format */
12064 1240446 void ha_innobase::position(const uchar *record) {
12065 uint len;
12066
12067
1/2
✓ Branch 0 taken 1240446 times.
✗ Branch 1 not taken.
1240446 DBUG_TRACE;
12068
3/6
✓ Branch 0 taken 1240446 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1240446 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1240446 times.
1240446 assert(m_prebuilt->trx == thd_to_trx(ha_thd()));
12069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1240446 times.
1240446 assert(table_share->is_missing_primary_key() ==
12070 (bool)m_prebuilt->clust_index_was_generated);
12071
12072
2/2
✓ Branch 0 taken 958874 times.
✓ Branch 1 taken 281572 times.
1240446 if (m_prebuilt->clust_index_was_generated) {
12073 /* No primary key was defined for the table and we
12074 generated the clustered index from row id: the
12075 row reference will be the row id, not any key value
12076 that MySQL knows of */
12077
12078 958874 len = DATA_ROW_ID_LEN;
12079
12080 958874 memcpy(ref, m_prebuilt->row_id, len);
12081 } else {
12082 /* Copy primary key as the row reference */
12083 281572 KEY *key_info = table->key_info + table_share->primary_key;
12084
1/2
✓ Branch 0 taken 281573 times.
✗ Branch 1 not taken.
281572 key_copy(ref, (uchar *)record, key_info, key_info->key_length);
12085 281573 len = key_info->key_length;
12086 }
12087
12088 /* We assume that the 'ref' value len is always fixed for the same
12089 table. */
12090
12091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1240447 times.
1240447 if (len != ref_length) {
12092 log_errlog(ERROR_LEVEL, ER_INNODB_DIFF_IN_REF_LEN, (ulong)len,
12093 (ulong)ref_length);
12094 }
12095 1240447 }
12096
12097 /** Set up base columns for virtual column
12098 @param[in] table the InnoDB table
12099 @param[in] field MySQL field
12100 @param[in,out] v_col virtual column to be set up */
12101 33429 void innodb_base_col_setup(dict_table_t *table, const Field *field,
12102 dict_v_col_t *v_col) {
12103 33429 int n = 0;
12104
12105
2/2
✓ Branch 0 taken 531818 times.
✓ Branch 1 taken 33429 times.
565247 for (uint i = 0; i < field->table->s->fields; ++i) {
12106 531818 const Field *base_field = field->table->field[i];
12107
12108
6/6
✓ Branch 0 taken 150711 times.
✓ Branch 1 taken 381107 times.
✓ Branch 2 taken 32845 times.
✓ Branch 3 taken 117866 times.
✓ Branch 4 taken 32845 times.
✓ Branch 5 taken 498973 times.
682529 if (!base_field->is_virtual_gcol() &&
12109 150711 bitmap_is_set(&field->gcol_info->base_columns_map, i)) {
12110 ulint z;
12111
12112
1/2
✓ Branch 0 taken 64261 times.
✗ Branch 1 not taken.
64261 for (z = 0; z < table->n_cols; z++) {
12113 64261 const char *name = table->get_col_name(z);
12114
2/2
✓ Branch 0 taken 32845 times.
✓ Branch 1 taken 31416 times.
64261 if (!innobase_strcasecmp(name, base_field->field_name)) {
12115 32845 break;
12116 }
12117 }
12118
12119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32845 times.
32845 ut_ad(z != table->n_cols);
12120
12121 32845 v_col->base_col[n] = table->get_col(z);
12122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32845 times.
32845 ut_ad(v_col->base_col[n]->ind == z);
12123 32845 n++;
12124 }
12125 }
12126 33429 }
12127
12128 /** Set up base columns for stored column
12129 @param[in] table InnoDB table
12130 @param[in] field MySQL field
12131 @param[in,out] s_col stored column */
12132 2231 void innodb_base_col_setup_for_stored(const dict_table_t *table,
12133 const Field *field, dict_s_col_t *s_col) {
12134 2231 ulint n = 0;
12135
12136
2/2
✓ Branch 0 taken 4583 times.
✓ Branch 1 taken 22 times.
4605 for (uint i = 0; i < field->table->s->fields; ++i) {
12137 4583 const Field *base_field = field->table->field[i];
12138
12139
8/8
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 4381 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 99 times.
✓ Branch 4 taken 2255 times.
✓ Branch 5 taken 2229 times.
✓ Branch 6 taken 2255 times.
✓ Branch 7 taken 2328 times.
9067 if (!innobase_is_v_fld(base_field) &&
12140 4484 bitmap_is_set(&field->gcol_info->base_columns_map, i)) {
12141 ulint z;
12142
1/2
✓ Branch 0 taken 4566 times.
✗ Branch 1 not taken.
4566 for (z = 0; z < table->n_cols; z++) {
12143 4566 const char *name = table->get_col_name(z);
12144
2/2
✓ Branch 0 taken 2255 times.
✓ Branch 1 taken 2311 times.
4566 if (!innobase_strcasecmp(name, base_field->field_name)) {
12145 2255 break;
12146 }
12147 }
12148
12149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2255 times.
2255 ut_ad(z != table->n_cols);
12150
12151 2255 s_col->base_col[n] = table->get_col(z);
12152 2255 n++;
12153
12154
2/2
✓ Branch 0 taken 2209 times.
✓ Branch 1 taken 46 times.
2255 if (n == s_col->num_base) {
12155 2209 break;
12156 }
12157 }
12158 }
12159 2231 }
12160
12161 /** If encryption is requested, check for master key availability
12162 and set the encryption flag in table flags
12163 @param[in,out] table table object
12164 @return on success DB_SUCCESS else DB_UNSPPORTED on failure */
12165 4278 dberr_t create_table_info_t::enable_master_key_encryption(dict_table_t *table) {
12166 4278 const char *encrypt = m_create_info->encrypt_type.str;
12167
12168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4278 times.
4278 if (Encryption::is_none(encrypt)) return (DB_SUCCESS);
12169
12170 /* If table is part of tablespace - no need for retrieving
12171 master key as tablespace key was already decrypted
12172 either by validate_first_page or during tablespace creation.
12173 Just set the encryption flag and return. */
12174
2/2
✓ Branch 0 taken 791 times.
✓ Branch 1 taken 3487 times.
4278 if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE)) {
12175 791 DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE);
12176 791 return (DB_SUCCESS);
12177 }
12178
12179 /* Set the encryption flag. */
12180 3487 byte *master_key = nullptr;
12181 uint32_t master_key_id;
12182
12183 /* Check if keyring is ready. */
12184 3487 Encryption::get_master_key(&master_key_id, &master_key);
12185
12186 3487 dberr_t err = DB_SUCCESS;
12187
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 3302 times.
3487 if (master_key == nullptr) {
12188
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
12189 185 err = DB_UNSUPPORTED;
12190 } else {
12191
1/2
✓ Branch 0 taken 3302 times.
✗ Branch 1 not taken.
3302 my_free(master_key);
12192 3302 DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE);
12193 }
12194
12195 3487 return (err);
12196 }
12197
12198 /** Retrive keyring encryption mode
12199 @param[in] encrypt_type from ENCRYPTION clause
12200 @param[in] explicit_encryption was ENCRYPTION clause used
12201 @param[in] flags tabelspace flags
12202 @retval FIL_ENCRYPTION_OFF tablespace should be skipped by
12203 encryption threads
12204 FIL_ENCRYPTION_DEFAULT online encryption allowed by
12205 encryption threads
12206 FIL_ENCRYPTION_ON table should be keyring encrypted */
12207 410425 static fil_encryption_t get_encryption_mode(const char *encrypt_type,
12208 bool explicit_encryption) {
12209
6/6
✓ Branch 0 taken 586 times.
✓ Branch 1 taken 409839 times.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 345 times.
✓ Branch 4 taken 241 times.
✓ Branch 5 taken 410184 times.
410425 if (explicit_encryption && innobase_strcasecmp(encrypt_type, "n") == 0) {
12210 241 return FIL_ENCRYPTION_OFF;
12211 }
12212
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 410107 times.
410184 if (Encryption::is_keyring(encrypt_type)) {
12213 77 return FIL_ENCRYPTION_ON;
12214 }
12215 410107 return FIL_ENCRYPTION_DEFAULT;
12216 }
12217
12218 85 dberr_t create_table_info_t::check_tablespace_key(
12219 const EncryptionKeyId encryption_key_id) {
12220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist(
12221 encryption_key_id, server_uuid)) {
12222 my_printf_error(
12223 ER_ILLEGAL_HA_CREATE_OPTION,
12224 "Seems that keyring is down. It is not possible to create encrypted "
12225 "tables "
12226 " without keyring. Please install a keyring and try again.",
12227 MYF(0));
12228 return (DB_UNSUPPORTED);
12229 }
12230 85 return DB_SUCCESS;
12231 }
12232
12233 /** Enable keyring encryption for table
12234 @param[in,out] table table to have its encryption flag set
12235 in case it should be KEYRING encrypted
12236 @param[out] keyring_encryption_mode FIL_ENCRYPTION_ON |
12237 FIL_ENCRYPTION_OFF | FIL_ENCRYPTION_DEFAULT
12238 @retval DB_UNSUPPORTED on error
12239 DB_SUCCESS on success */
12240 409537 dberr_t create_table_info_t::enable_keyring_encryption(
12241 dict_table_t *table, fil_encryption_t &keyring_encryption_mode) {
12242 409537 keyring_encryption_mode =
12243 819074 get_encryption_mode(m_create_info->encrypt_type.str,
12244 409537 m_create_info->used_fields & HA_CREATE_USED_ENCRYPT);
12245
12246
2/2
✓ Branch 0 taken 409460 times.
✓ Branch 1 taken 77 times.
818997 bool is_encrypted = keyring_encryption_mode == FIL_ENCRYPTION_ON ||
12247
3/4
✓ Branch 0 taken 409460 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 409452 times.
818920 (keyring_encryption_mode == FIL_ENCRYPTION_DEFAULT &&
12248 409460 Encryption::is_online_encryption_on());
12249
12250
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 409452 times.
409537 if (is_encrypted)
12251 85 DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE);
12252
12253
3/4
✓ Branch 0 taken 409452 times.
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 409452 times.
409537 if (is_encrypted || m_create_info->was_encryption_key_id_set)
12254 85 return check_tablespace_key(m_create_info->encryption_key_id);
12255
12256 409452 return DB_SUCCESS;
12257 }
12258
12259 /** Create a table definition to an InnoDB database.
12260 @param[in] dd_table dd::Table or nullptr for intrinsic table
12261 @param[in] old_part_table dd::Table from an old partition for partitioned
12262 table, NULL otherwise.
12263 @return HA_* level error */
12264 429473 [[nodiscard]] inline int create_table_info_t::create_table_def(
12265 const dd::Table *dd_table, const dd::Table *old_part_table) {
12266 dict_table_t *table;
12267 ulint n_cols;
12268 429473 dberr_t err = DB_SUCCESS;
12269 ulint col_type;
12270 ulint col_len;
12271 ulint compressed;
12272 ulint i;
12273 429473 ulint j = 0;
12274 429473 ulint doc_id_col = 0;
12275 429473 bool has_doc_id_col = false;
12276 mem_heap_t *heap;
12277 429473 ulint num_v = 0;
12278 429473 ulint num_m_v = 0;
12279 429473 space_id_t space_id = 0;
12280 429473 dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID;
12281 ulint actual_n_cols;
12282
12283 fil_encryption_t keyring_encryption_option =
12284 429473 Encryption::none_explicitly_specified(m_create_info->explicit_encryption,
12285 429473 m_create_info->encrypt_type.str)
12286
2/2
✓ Branch 0 taken 15629 times.
✓ Branch 1 taken 413845 times.
429474 ? FIL_ENCRYPTION_OFF
12287 429474 : FIL_ENCRYPTION_DEFAULT;
12288
12289 429474 uint32_t i_c = 0;
12290 429474 uint32_t c_c = 0;
12291 429474 uint32_t t_c = 0;
12292 429474 uint32_t c_r_v = 0;
12293
12294
1/2
✓ Branch 0 taken 429474 times.
✗ Branch 1 not taken.
429474 DBUG_TRACE;
12295
5/8
✓ Branch 0 taken 429474 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 429473 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 429465 times.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
429474 DBUG_PRINT("enter", ("table_name: %s", m_table_name));
12296
12297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429473 times.
429473 assert(m_trx->mysql_thd == m_thd);
12298
12299 bool part_table_with_instant_cols =
12300
5/6
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 429388 times.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 12 times.
429473 (old_part_table != nullptr && dd_table_has_row_versions(*old_part_table));
12301
12302 /* MySQL does the name length check. But we do additional check
12303 on the name length here */
12304 429473 const size_t table_name_len = strlen(m_table_name);
12305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429473 times.
429473 if (table_name_len > MAX_FULL_NAME_LEN) {
12306 push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME,
12307 "InnoDB: Table Name or Database Name is too long");
12308
12309 return HA_ERR_WRONG_TABLE_NAME;
12310 }
12311
12312 /* Make sure that the table name is acceptable. */
12313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429473 times.
429473 if (m_table_name[table_name_len - 1] == '/') {
12314 push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME,
12315 "InnoDB: Table name is empty");
12316
12317 return HA_ERR_WRONG_TABLE_NAME;
12318 }
12319
12320 fts_aux_table_t aux_table;
12321
3/4
✓ Branch 0 taken 429473 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 429447 times.
429473 if (fts_is_aux_table_name(&aux_table, m_table_name, strlen(m_table_name))) {
12322
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 push_warning_printf(
12323 m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME,
12324 "Invalid table name. `%s` has the form of an FTS auxiliary table name",
12325 m_table_name);
12326 26 return HA_ERR_WRONG_TABLE_NAME;
12327 }
12328
12329 429447 n_cols = m_form->s->fields;
12330
12331 /* Find out any virtual column */
12332
2/2
✓ Branch 0 taken 3352337 times.
✓ Branch 1 taken 429447 times.
3781784 for (i = 0; i < n_cols; i++) {
12333 3352337 Field *field = m_form->field[i];
12334
12335
7/10
✓ Branch 0 taken 9273 times.
✓ Branch 1 taken 3343064 times.
✓ Branch 2 taken 2227 times.
✓ Branch 3 taken 7046 times.
✓ Branch 4 taken 3345291 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3345291 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3352337 times.
3352337 ut_ad(!(!innobase_is_v_fld(field) && innobase_is_multi_value_fld(field)));
12336
12337
4/4
✓ Branch 0 taken 9273 times.
✓ Branch 1 taken 3343064 times.
✓ Branch 2 taken 7046 times.
✓ Branch 3 taken 2227 times.
3352337 if (innobase_is_v_fld(field)) {
12338 7046 num_v++;
12339
12340
3/4
✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 6808 times.
7046 if (innobase_is_multi_value_fld(field)) {
12341 238 num_m_v++;
12342 }
12343 }
12344 }
12345
12346 /* Check whether there already exists a FTS_DOC_ID column */
12347
3/4
✓ Branch 0 taken 429447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 429408 times.
429447 if (create_table_check_doc_id_col(m_trx->mysql_thd, m_form, &doc_id_col)) {
12348 /* Raise error if the Doc ID column is of wrong type or name */
12349
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 38 times.
39 if (doc_id_col == ULINT_UNDEFINED) {
12350 1 err = DB_ERROR;
12351 1 goto error_ret;
12352 } else {
12353 38 has_doc_id_col = true;
12354 }
12355 }
12356
12357 /* For single-table tablespaces, we pass 0 as the space id, and then
12358 determine the actual space id when the tablespace is created. */
12359
2/2
✓ Branch 0 taken 30520 times.
✓ Branch 1 taken 398926 times.
429446 if (DICT_TF_HAS_SHARED_SPACE(m_flags)) {
12360
3/6
✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30520 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30520 times.
30520 ut_ad(m_tablespace != nullptr && m_tablespace[0] != '\0');
12361
12362
1/2
✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
30520 space_id = fil_space_get_id_by_name(m_tablespace);
12363
2/4
✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30520 times.
✗ Branch 3 not taken.
30520 dd_space_id = (dd_table != nullptr ? dd_table->tablespace_id()
12364 : dd::INVALID_OBJECT_ID);
12365 }
12366
12367 /* Adjust the number of columns for the FTS hidden field */
12368 429446 actual_n_cols = n_cols;
12369
4/4
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428853 times.
✓ Branch 2 taken 573 times.
✓ Branch 3 taken 20 times.
429446 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) {
12370 573 actual_n_cols += 1;
12371 }
12372
12373
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 429373 times.
429446 if (part_table_with_instant_cols) {
12374
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 dd_table_get_column_counters(*old_part_table, i_c, c_c, t_c, c_r_v);
12375 }
12376
12377
1/2
✓ Branch 0 taken 429447 times.
✗ Branch 1 not taken.
429446 table = dict_mem_table_create(m_table_name, space_id, actual_n_cols, num_v,
12378 num_m_v, m_flags, m_flags2, t_c - c_c);
12379
12380 /* Set dd tablespace id */
12381 429447 table->dd_space_id = dd_space_id;
12382
12383 /* Set the hidden doc_id column. */
12384
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428854 times.
429447 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) {
12385
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 573 times.
593 table->fts->doc_col = has_doc_id_col ? doc_id_col : n_cols - num_v;
12386 }
12387
12388
2/2
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 429011 times.
429447 if (DICT_TF_HAS_DATA_DIR(m_flags)) {
12389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 435 times.
435 ut_a(strlen(m_remote_path) != 0);
12390
12391
1/2
✓ Branch 0 taken 435 times.
✗ Branch 1 not taken.
435 table->data_dir_path = mem_heap_strdup(table->heap, m_remote_path);
12392
12393 } else {
12394 429011 table->data_dir_path = nullptr;
12395 }
12396
12397
2/2
✓ Branch 0 taken 30520 times.
✓ Branch 1 taken 398927 times.
429446 if (DICT_TF_HAS_SHARED_SPACE(m_flags)) {
12398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30520 times.
30520 ut_ad(strlen(m_tablespace));
12399
1/2
✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
30520 table->tablespace = mem_heap_strdup(table->heap, m_tablespace);
12400 } else {
12401 398927 table->tablespace = nullptr;
12402 }
12403
12404 /* Initialize row version and column counts for new table */
12405
2/2
✓ Branch 0 taken 429373 times.
✓ Branch 1 taken 73 times.
429446 if (!part_table_with_instant_cols) {
12406 429373 table->current_row_version = 0;
12407 429373 table->initial_col_count = n_cols - num_v;
12408 429373 table->current_col_count = table->initial_col_count;
12409 429373 table->total_col_count = table->initial_col_count;
12410 } else {
12411 /* This is a new partition getting created. We need to inherit INSTANT
12412 instant metadata from old partition table */
12413 73 table->initial_col_count = i_c;
12414 73 table->current_col_count = c_c;
12415 73 table->total_col_count = t_c;
12416 73 table->current_row_version = c_r_v;
12417 73 table->discard_after_ddl = true;
12418
12419 #ifdef UNIV_DEBUG
12420 /* Get and set current row version for table */
12421 73 uint32_t v = 0;
12422
6/10
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 515 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 515 times.
✓ Branch 9 taken 73 times.
588 for (auto col : old_part_table->columns()) {
12423
3/4
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 445 times.
515 if (dd_column_is_dropped(col)) {
12424
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 uint32_t value = dd_column_get_version_dropped(col);
12425 70 v = std::max(v, value);
12426 70 continue;
12427 70 }
12428
12429
3/4
✓ Branch 0 taken 445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 333 times.
445 if (dd_column_is_added(col)) {
12430
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 uint32_t value = dd_column_get_version_added(col);
12431 112 v = std::max(v, value);
12432 112 continue;
12433 112 }
12434 }
12435
2/4
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
73 ut_ad(dd_is_valid_row_version(v));
12436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 ut_ad(table->current_row_version == v);
12437 #endif
12438 }
12439
12440
1/2
✓ Branch 0 taken 429447 times.
✗ Branch 1 not taken.
429446 heap = mem_heap_create(1000, UT_LOCATION_HERE);
12441
12442
2/2
✓ Branch 0 taken 3352330 times.
✓ Branch 1 taken 429444 times.
3781774 for (i = 0; i < n_cols; i++) {
12443 ulint nulls_allowed;
12444 ulint unsigned_type;
12445 ulint binary_type;
12446 ulint long_true_varchar;
12447 ulint charset_no;
12448 ulint is_virtual;
12449 ulint is_multi_val;
12450 3352330 bool is_stored = false;
12451
12452 3352330 Field *field = m_form->field[i];
12453
12454 /* Generate a unique column name by pre-pending table-name for
12455 intrinsic tables. For other tables (including normal
12456 temporary) column names are unique. If not, MySQL layer will
12457 block such statement.
12458 This is work-around fix till Optimizer can handle this issue
12459 (probably 5.7.4+). */
12460 char field_name[MAX_FULL_NAME_LEN + 2 + 10];
12461
12462
6/8
✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2605781 times.
✓ Branch 3 taken 746549 times.
✓ Branch 4 taken 2605781 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2605781 times.
✓ Branch 7 taken 746549 times.
3352330 if (table->is_intrinsic() && field->table) {
12463 2605781 snprintf(field_name, sizeof(field_name), "%s_%s_" ULINTPF,
12464 2605781 field->table->alias, field->field_name, i);
12465
12466 } else {
12467 746549 snprintf(field_name, sizeof(field_name), "%s", field->field_name);
12468 }
12469
12470
1/2
✓ Branch 0 taken 3352331 times.
✗ Branch 1 not taken.
3352330 col_type = get_innobase_type_from_mysql_type(&unsigned_type, field);
12471
12472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3352331 times.
3352331 if (!col_type) {
12473 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
12474 ER_CANT_CREATE_TABLE,
12475 "Error creating table '%s' with"
12476 " column '%s'. Please check its"
12477 " column type and try to re-create"
12478 " the table with an appropriate"
12479 " column type.",
12480 table->name.m_name, field->field_name);
12481 goto err_col;
12482 }
12483
12484
2/2
✓ Branch 0 taken 1220668 times.
✓ Branch 1 taken 2131663 times.
3352331 nulls_allowed = field->is_nullable() ? 0 : DATA_NOT_NULL;
12485
3/4
✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1710953 times.
✓ Branch 3 taken 1641377 times.
3352331 binary_type = field->binary() ? DATA_BINARY_TYPE : 0;
12486
12487 3352330 charset_no = 0;
12488
12489
3/4
✓ Branch 0 taken 3352331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1712989 times.
✓ Branch 3 taken 1639342 times.
3352330 if (dtype_is_string_type(col_type)) {
12490
1/2
✓ Branch 0 taken 1712989 times.
✗ Branch 1 not taken.
1712989 charset_no = (ulint)field->charset()->number;
12491
12492
3/4
✓ Branch 0 taken 1712989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1712988 times.
1712989 DBUG_EXECUTE_IF("simulate_max_char_col",
12493 charset_no = MAX_CHAR_COLL_NUM + 1;);
12494
12495
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1712988 times.
1712989 if (charset_no > MAX_CHAR_COLL_NUM) {
12496 /* in data0type.h we assume that the
12497 number fits in one byte in prtype */
12498
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
12499 ER_CANT_CREATE_TABLE,
12500 "In InnoDB, charset-collation codes"
12501 " must be below 256."
12502 " Unsupported code %lu.",
12503 (ulong)charset_no);
12504
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mem_heap_free(heap);
12505
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dict_mem_table_free(table);
12506
12507 1 return ER_CANT_CREATE_TABLE;
12508 }
12509 }
12510
12511
1/2
✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
3352330 col_len = field->pack_length();
12512
12513 /* The MySQL pack length contains 1 or 2 bytes length field
12514 for a true VARCHAR. Let us subtract that, so that the InnoDB
12515 column length in the InnoDB data dictionary is the real
12516 maximum byte length of the actual data. */
12517
12518 3352330 long_true_varchar = 0;
12519
12520
3/4
✓ Branch 0 taken 3352329 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1351959 times.
✓ Branch 3 taken 2000370 times.
3352330 if (field->type() == MYSQL_TYPE_VARCHAR) {
12521
1/2
✓ Branch 0 taken 1351959 times.
✗ Branch 1 not taken.
1351959 col_len -= field->get_length_bytes();
12522
12523
3/4
✓ Branch 0 taken 1351959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 357452 times.
✓ Branch 3 taken 994507 times.
1351959 if (field->get_length_bytes() == 2) {
12524 357452 long_true_varchar = DATA_LONG_TRUE_VARCHAR;
12525 }
12526 }
12527
12528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3352329 times.
3352329 if (col_type == DATA_POINT) {
12529 col_len = DATA_POINT_LEN;
12530 }
12531
12532
4/4
✓ Branch 0 taken 9273 times.
✓ Branch 1 taken 3343056 times.
✓ Branch 2 taken 7046 times.
✓ Branch 3 taken 2227 times.
3352329 is_virtual = (innobase_is_v_fld(field)) ? DATA_VIRTUAL : 0;
12533 3352329 is_stored = innobase_is_s_fld(field);
12534 /* Check if the the field has COMPRESSED attribute */
12535 3352329 compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED)
12536
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 3351919 times.
3352330 ? DATA_COMPRESSED
12537 : 0;
12538
12539
3/4
✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 3352092 times.
3352330 is_multi_val = innobase_is_multi_value_fld(field) ? DATA_MULTI_VALUE : 0;
12540
12541 /* First check whether the column to be added has a
12542 system reserved name. */
12543
3/4
✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3352328 times.
3352330 if (dict_col_name_is_reserved(field_name)) {
12544
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_COLUMN_NAME, MYF(0), field_name);
12545 2 err_col:
12546
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_mem_table_free(table);
12547
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mem_heap_free(heap);
12548
12549 2 err = DB_ERROR;
12550 2 goto error_ret;
12551 }
12552
12553
2/2
✓ Branch 0 taken 3345282 times.
✓ Branch 1 taken 7046 times.
3352328 if (!is_virtual) {
12554 3345282 uint32_t v_added = UINT32_UNDEFINED;
12555 3345282 uint32_t v_dropped = UINT32_UNDEFINED;
12556 3345282 uint32_t phy_pos = UINT32_UNDEFINED;
12557
12558
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 3344994 times.
3345282 if (part_table_with_instant_cols) {
12559 const dd::Column *old_part_col =
12560
1/2
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
288 dd_find_column(old_part_table, field_name);
12561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
288 ut_ad(old_part_col != nullptr);
12562
12563 /* Get version added */
12564
1/2
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
288 v_added = dd_column_get_version_added(old_part_col);
12565
12566 /* This columns must be present */
12567
2/4
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 288 times.
288 ut_ad(!dd_column_is_dropped(old_part_col));
12568
12569 /* Get physical pos */
12570 288 const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS];
12571
4/8
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 288 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 288 times.
288 ut_ad(old_part_col->se_private_data().exists(s));
12572
3/6
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 288 times.
✗ Branch 5 not taken.
288 old_part_col->se_private_data().get(s, &phy_pos);
12573 }
12574
12575
1/2
✓ Branch 0 taken 3345282 times.
✗ Branch 1 not taken.
3345282 dict_mem_table_add_col(
12576 table, heap, field_name, col_type,
12577 6690562 dtype_form_prtype((ulint)field->type() | nulls_allowed |
12578
1/2
✓ Branch 0 taken 3345282 times.
✗ Branch 1 not taken.
3345281 unsigned_type | binary_type |
12579 long_true_varchar | compressed,
12580 charset_no),
12581
2/4
✓ Branch 0 taken 3345281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3345281 times.
✗ Branch 3 not taken.
3345282 col_len, !field->is_hidden_by_system(), phy_pos, v_added, v_dropped);
12582
12583
3/4
✓ Branch 0 taken 3345281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 3345169 times.
3345282 if (dd_is_valid_row_version(v_added)) {
12584
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 mem_heap_t *instant_heap = mem_heap_create(1000, UT_LOCATION_HERE);
12585 const dd::Column *old_part_col =
12586
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 dd_find_column(old_part_table, field_name);
12587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 ut_ad(old_part_col != nullptr);
12588
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 dict_col_t *col = table->get_col(table->n_def - 1);
12589
2/4
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
112 dd_parse_default_value(old_part_col->se_private_data(), col, heap);
12590
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 mem_heap_free(instant_heap);
12591 }
12592 } else {
12593
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 6808 times.
7046 if (is_multi_val) {
12594
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 col_len = field->key_length();
12595 }
12596
1/2
✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
7046 dict_mem_table_add_v_col(
12597 table, heap, field_name, col_type,
12598
1/2
✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
7046 dtype_form_prtype((ulint)field->type() | nulls_allowed |
12599 7046 unsigned_type | binary_type |
12600
1/2
✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
7046 long_true_varchar | is_virtual | is_multi_val |
12601 compressed,
12602 charset_no),
12603 7046 col_len, i, field->gcol_info->non_virtual_base_columns(),
12604
1/2
✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
7046 !field->is_hidden_by_system());
12605 }
12606
12607
2/2
✓ Branch 0 taken 2227 times.
✓ Branch 1 taken 3350100 times.
3352327 if (is_stored) {
12608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2227 times.
2227 ut_ad(!is_virtual);
12609 /* Added stored column in m_s_cols list. */
12610
1/2
✓ Branch 0 taken 2227 times.
✗ Branch 1 not taken.
2227 dict_mem_table_add_s_col(table,
12611 2227 field->gcol_info->non_virtual_base_columns());
12612 }
12613 }
12614
12615
2/2
✓ Branch 0 taken 3513 times.
✓ Branch 1 taken 425931 times.
429444 if (num_v) {
12616
2/2
✓ Branch 0 taken 18958 times.
✓ Branch 1 taken 3513 times.
22471 for (i = 0; i < n_cols; i++) {
12617 dict_v_col_t *v_col;
12618
12619 18958 Field *field = m_form->field[i];
12620
12621
4/4
✓ Branch 0 taken 9006 times.
✓ Branch 1 taken 9952 times.
✓ Branch 2 taken 1960 times.
✓ Branch 3 taken 7046 times.
18958 if (!innobase_is_v_fld(field)) {
12622 11912 continue;
12623 }
12624
12625
1/2
✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
7046 v_col = dict_table_get_nth_v_col(table, j);
12626
12627 7046 j++;
12628
12629
1/2
✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
7046 innodb_base_col_setup(table, field, v_col);
12630 }
12631 }
12632
12633 /** Fill base columns for the stored column present in the list. */
12634
5/6
✓ Branch 0 taken 2131 times.
✓ Branch 1 taken 427313 times.
✓ Branch 2 taken 2131 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2131 times.
✓ Branch 5 taken 427313 times.
429444 if (table->s_cols && table->s_cols->size()) {
12635
2/2
✓ Branch 0 taken 12449 times.
✓ Branch 1 taken 2131 times.
14580 for (i = 0; i < n_cols; i++) {
12636 12449 Field *field = m_form->field[i];
12637
12638
2/2
✓ Branch 0 taken 10222 times.
✓ Branch 1 taken 2227 times.
12449 if (!innobase_is_s_fld(field)) {
12639 10222 continue;
12640 }
12641
12642 2227 dict_s_col_list::iterator it;
12643
1/2
✓ Branch 0 taken 2390 times.
✗ Branch 1 not taken.
2390 for (it = table->s_cols->begin(); it != table->s_cols->end(); ++it) {
12644 2390 dict_s_col_t s_col = *it;
12645
12646
2/2
✓ Branch 0 taken 2227 times.
✓ Branch 1 taken 163 times.
2390 if (s_col.s_pos == i) {
12647
1/2
✓ Branch 0 taken 2227 times.
✗ Branch 1 not taken.
2227 innodb_base_col_setup_for_stored(table, field, &s_col);
12648 2227 break;
12649 }
12650 }
12651 }
12652 }
12653
12654 /* Add the FTS doc_id hidden column. */
12655
4/4
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428851 times.
✓ Branch 2 taken 573 times.
✓ Branch 3 taken 20 times.
429444 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) {
12656
1/2
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
573 fts_add_doc_id_column(table, heap);
12657 }
12658
12659
2/2
✓ Branch 0 taken 413815 times.
✓ Branch 1 taken 15629 times.
429444 if (keyring_encryption_option != FIL_ENCRYPTION_OFF) {
12660 413815 err =
12661 413815 (Encryption::is_master_key_encryption(m_create_info->encrypt_type.str))
12662
3/4
✓ Branch 0 taken 4278 times.
✓ Branch 1 taken 409537 times.
✓ Branch 2 taken 4278 times.
✗ Branch 3 not taken.
413815 ? enable_master_key_encryption(table)
12663
1/2
✓ Branch 0 taken 409537 times.
✗ Branch 1 not taken.
409537 : enable_keyring_encryption(table, keyring_encryption_option);
12664 }
12665
12666
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 429259 times.
429444 if (err != DB_SUCCESS) {
12667
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 dict_mem_table_free(table);
12668
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 mem_heap_free(heap);
12669 185 goto error_ret;
12670 }
12671
12672
3/4
✓ Branch 0 taken 429259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 228814 times.
✓ Branch 3 taken 200445 times.
429259 if (table->is_temporary()) {
12673
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 228813 times.
228814 if (m_create_info->compress.length > 0) {
12674
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
12675 "InnoDB: Compression not supported for "
12676 "temporary tables");
12677
12678 1 err = DB_UNSUPPORTED;
12679
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dict_mem_table_free(table);
12680 } else {
12681 /* Get a new table ID */
12682
1/2
✓ Branch 0 taken 228813 times.
✗ Branch 1 not taken.
228813 dict_table_assign_new_id(table);
12683
12684 /* Create temp tablespace if configured. */
12685 228813 KeyringEncryptionKeyIdInfo keyring_encryption_key_id;
12686 228813 keyring_encryption_key_id.was_encryption_key_id_set = false;
12687
1/2
✓ Branch 0 taken 228812 times.
✗ Branch 1 not taken.
228813 err = dict_build_tablespace_for_table(table, m_create_info, m_trx,
12688 FIL_ENCRYPTION_DEFAULT,
12689 keyring_encryption_key_id);
12690
12691
2/2
✓ Branch 0 taken 228809 times.
✓ Branch 1 taken 3 times.
228812 if (err == DB_SUCCESS) {
12692 /* Temp-table are maintained in memory and so
12693 can_be_evicted is false. */
12694 mem_heap_t *temp_table_heap;
12695
12696
1/2
✓ Branch 0 taken 228809 times.
✗ Branch 1 not taken.
228809 temp_table_heap = mem_heap_create(256, UT_LOCATION_HERE);
12697
12698 /* For intrinsic table (given that they are
12699 not shared beyond session scope), add
12700 it to session specific THD structure
12701 instead of adding it to dictionary cache. */
12702
3/4
✓ Branch 0 taken 228809 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182644 times.
✓ Branch 3 taken 46165 times.
228809 if (table->is_intrinsic()) {
12703
1/2
✓ Branch 0 taken 182644 times.
✗ Branch 1 not taken.
182644 add_table_to_thread_cache(table, temp_table_heap, m_thd);
12704
12705 } else {
12706
1/2
✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
46165 dict_table_add_system_columns(table, temp_table_heap);
12707
12708
1/2
✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
46165 dict_sys_mutex_enter();
12709
1/2
✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
46165 dict_table_add_to_cache(table, false);
12710
1/2
✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
46165 dict_sys_mutex_exit();
12711 }
12712
12713
4/6
✓ Branch 0 taken 228809 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 228808 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
228809 DBUG_EXECUTE_IF("ib_ddl_crash_during_create2", DBUG_SUICIDE(););
12714
12715
1/2
✓ Branch 0 taken 228808 times.
✗ Branch 1 not taken.
228808 mem_heap_free(temp_table_heap);
12716 } else {
12717
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 dict_mem_table_free(table);
12718 }
12719 }
12720
12721 } else {
12722 200445 const char *algorithm = m_create_info->compress.str;
12723
12724 200445 err = DB_SUCCESS;
12725
12726 435895 if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE) &&
12727
6/6
✓ Branch 0 taken 35005 times.
✓ Branch 1 taken 165440 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 35003 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 200443 times.
200447 m_create_info->compress.length > 0 &&
12728
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 !Compression::is_none(algorithm)) {
12729
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
12730 "InnoDB: Compression not supported for "
12731 "shared tablespaces");
12732
12733 2 algorithm = nullptr;
12734
12735 2 err = DB_UNSUPPORTED;
12736
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 dict_mem_table_free(table);
12737
12738
1/2
✓ Branch 0 taken 200443 times.
✗ Branch 1 not taken.
200443 } else if (Compression::validate(algorithm) != DB_SUCCESS ||
12739
6/6
✓ Branch 0 taken 200442 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 200055 times.
✓ Branch 3 taken 387 times.
✓ Branch 4 taken 493 times.
✓ Branch 5 taken 199950 times.
400498 m_form->s->row_type == ROW_TYPE_COMPRESSED ||
12740
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 199950 times.
200055 m_create_info->key_block_size > 0) {
12741 493 algorithm = nullptr;
12742 }
12743
12744 KeyringEncryptionKeyIdInfo keyring_encryption_key_id(
12745 200445 m_create_info->was_encryption_key_id_set,
12746 200445 m_create_info->encryption_key_id);
12747
12748
2/2
✓ Branch 0 taken 200443 times.
✓ Branch 1 taken 2 times.
200445 if (err == DB_SUCCESS) {
12749
1/2
✓ Branch 0 taken 200397 times.
✗ Branch 1 not taken.
200443 err = row_create_table_for_mysql(table, algorithm, m_create_info, m_trx,
12750 heap,
12751 keyring_encryption_option,
12752 keyring_encryption_key_id);
12753
12754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200397 times.
200397 if (err == DB_IO_NO_PUNCH_HOLE_FS) {
12755 ut_ad(!dict_table_in_shared_tablespace(table));
12756 my_error(ER_INNODB_COMPRESSION_FAILURE, MYF(0),
12757 "Punch hole not supported by the filesystem or the tablespace "
12758 "page size is not large enough.");
12759 }
12760
12761
4/4
✓ Branch 0 taken 200383 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 200310 times.
200397 if (err == DB_SUCCESS && part_table_with_instant_cols) {
12762 /* Set phy_pos for system cols */
12763
12764 219 auto fn = [&](uint32_t sys_col, const char *name) {
12765 219 uint32_t phy_pos = UINT32_UNDEFINED;
12766
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 dict_col_t *col = table->get_sys_col(sys_col);
12767
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 const dd::Column *old_part_col = dd_find_column(old_part_table, name);
12768
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 157 times.
219 if (old_part_col == nullptr) {
12769 /* If PK exists, DB_ROW_ID won't be part of table definition. */
12770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 ut_ad(strcmp(name, "DB_ROW_ID") == 0);
12771 62 return;
12772 }
12773
12774 157 const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS];
12775
4/8
✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 157 times.
157 ut_ad(old_part_col->se_private_data().exists(s));
12776
3/6
✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
157 old_part_col->se_private_data().get(s, &phy_pos);
12777 157 col->set_phy_pos(phy_pos);
12778 73 };
12779
12780
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 fn(DATA_ROW_ID, "DB_ROW_ID");
12781
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 fn(DATA_TRX_ID, "DB_TRX_ID");
12782
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 fn(DATA_ROLL_PTR, "DB_ROLL_PTR");
12783
12784 /* Add INSTANT DROP columns metadata */
12785 73 IF_DEBUG(uint32_t row_version = 0;)
12786
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 fill_dict_dropped_columns(old_part_table, table,
12787 IF_DEBUG(row_version, ) heap);
12788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 ut_ad(row_version <= table->current_row_version);
12789 }
12790 }
12791
12792
4/6
✓ Branch 0 taken 200399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 200379 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
200399 DBUG_EXECUTE_IF("ib_crash_during_create_for_encryption", DBUG_SUICIDE(););
12793 }
12794
12795
1/2
✓ Branch 0 taken 429191 times.
✗ Branch 1 not taken.
429191 mem_heap_free(heap);
12796
12797
2/4
✓ Branch 0 taken 429191 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 429191 times.
429191 DBUG_EXECUTE_IF("ib_create_err_tablespace_exist",
12798 err = DB_TABLESPACE_EXISTS;);
12799
12800
2/4
✓ Branch 0 taken 429191 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 429191 times.
429191 if (err == DB_DUPLICATE_KEY || err == DB_TABLESPACE_EXISTS) {
12801 char display_name[FN_REFLEN];
12802 char *buf_end =
12803 innobase_convert_identifier(display_name, sizeof(display_name) - 1,
12804 m_table_name, strlen(m_table_name), m_thd);
12805
12806 *buf_end = '\0';
12807
12808 my_error(
12809 err == DB_DUPLICATE_KEY ? ER_TABLE_EXISTS_ERROR : ER_TABLESPACE_EXISTS,
12810 MYF(0), display_name);
12811
12812 if (err == DB_DUPLICATE_KEY) {
12813 /* 'this' may not be ready for get_dup_key(), see same
12814 error tweaking in rename_table(). */
12815 err = DB_ERROR;
12816 }
12817 }
12818
12819
4/4
✓ Branch 0 taken 429171 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 588 times.
✓ Branch 3 taken 428583 times.
429191 if (err == DB_SUCCESS && (m_flags2 & DICT_TF2_FTS)) {
12820
1/2
✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
588 dict_sys_mutex_enter();
12821
1/2
✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
588 fts_optimize_add_table(table);
12822
1/2
✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
588 dict_sys_mutex_exit();
12823 }
12824
12825
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 429171 times.
429191 if (err == DB_SUCCESS) {
12826 429171 m_table = table;
12827 }
12828
12829 20 error_ret:
12830
1/2
✓ Branch 0 taken 429379 times.
✗ Branch 1 not taken.
429379 return convert_error_code_to_mysql(err, m_flags, m_thd);
12831 429406 }
12832
12833 template <typename Index>
12834 const dd::Index *get_my_dd_index(const Index *index);
12835
12836 template <>
12837 979 const dd::Index *get_my_dd_index<dd::Index>(const dd::Index *dd_index) {
12838 979 return dd_index;
12839 }
12840
12841 template <>
12842 const dd::Index *get_my_dd_index<dd::Partition_index>(
12843 const dd::Partition_index *dd_index) {
12844 return (dd_index != nullptr) ? &dd_index->index() : nullptr;
12845 }
12846
12847 /** Creates an index in an InnoDB database. */
12848 191703 inline int create_index(
12849 trx_t *trx, /*!< in: InnoDB transaction handle */
12850 const TABLE *form, /*!< in: information on table
12851 columns and indexes */
12852 uint32_t flags, /*!< in: InnoDB table flags */
12853 const char *table_name, /*!< in: table name */
12854 uint key_num, /*!< in: index number */
12855 const dd::Table *dd_table) /*!< in: dd::Table for the table*/
12856 {
12857 dict_index_t *index;
12858 int error;
12859 const KEY *key;
12860 ulint ind_type;
12861 ulint *field_lengths;
12862 191703 uint32_t srid = 0;
12863 191703 bool has_srid = false;
12864 191703 bool multi_val_idx = false;
12865
12866
1/2
✓ Branch 0 taken 191703 times.
✗ Branch 1 not taken.
191703 DBUG_TRACE;
12867
12868 191703 key = form->key_info + key_num;
12869
12870 /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
12871
2/4
✓ Branch 0 taken 191703 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 191703 times.
191703 ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
12872
12873
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 191702 times.
191703 if (key->key_length == 0) {
12874
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_KEY_COLUMN, MYF(0), key->key_part->field->field_name);
12875 1 return ER_WRONG_KEY_COLUMN;
12876 }
12877 191702 ind_type = 0;
12878
2/2
✓ Branch 0 taken 979 times.
✓ Branch 1 taken 190723 times.
191702 if (key->flags & HA_SPATIAL) {
12879 979 ind_type = DICT_SPATIAL;
12880
2/2
✓ Branch 0 taken 767 times.
✓ Branch 1 taken 189956 times.
190723 } else if (key->flags & HA_FULLTEXT) {
12881 767 ind_type = DICT_FTS;
12882 }
12883
12884
2/2
✓ Branch 0 taken 979 times.
✓ Branch 1 taken 190723 times.
191702 if (ind_type == DICT_SPATIAL) {
12885
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 862 times.
979 ulint dd_index_num = key_num + ((form->s->primary_key == MAX_KEY) ? 1 : 0);
12886
12887
2/4
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
979 const auto *dd_index_auto = dd_table->indexes()[dd_index_num];
12888
12889
1/2
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
979 const dd::Index *dd_index = get_my_dd_index(dd_index_auto);
12890
2/4
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 979 times.
979 ut_ad(dd_index->name() == key->name);
12891
12892 size_t geom_col_idx;
12893
2/4
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
979 for (geom_col_idx = 0; geom_col_idx < dd_index->elements().size();
12894 ++geom_col_idx) {
12895
5/10
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 979 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 979 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 979 times.
✗ Branch 9 not taken.
979 if (!dd_index->elements()[geom_col_idx]->column().is_se_hidden()) break;
12896 }
12897
3/6
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 979 times.
✗ Branch 5 not taken.
979 const dd::Column &col = dd_index->elements()[geom_col_idx]->column();
12898
1/2
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
979 has_srid = col.srs_id().has_value();
12899
4/6
✓ Branch 0 taken 954 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 954 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 954 times.
✗ Branch 5 not taken.
979 srid = has_srid ? col.srs_id().value() : 0;
12900 }
12901
12902
2/2
✓ Branch 0 taken 1746 times.
✓ Branch 1 taken 189956 times.
191702 if (ind_type != 0) {
12903 3492 index = dict_mem_index_create(table_name, key->name, 0, ind_type,
12904
1/2
✓ Branch 0 taken 1746 times.
✗ Branch 1 not taken.
1746 key->user_defined_key_parts);
12905
12906
2/2
✓ Branch 0 taken 1879 times.
✓ Branch 1 taken 1746 times.
3625 for (ulint i = 0; i < key->user_defined_key_parts; i++) {
12907 1879 KEY_PART_INFO *key_part = key->key_part + i;
12908
12909 /* We do not support special (Fulltext or Spatial)
12910 index on virtual columns */
12911
3/4
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 1835 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
1879 if (innobase_is_v_fld(key_part->field)) {
12912 ut_d(ut_error);
12913 ut_o(return HA_ERR_UNSUPPORTED);
12914 }
12915
12916 1879 index->add_field(key_part->field->field_name, 0,
12917
1/2
✓ Branch 0 taken 1879 times.
✗ Branch 1 not taken.
1879 !(key_part->key_part_flag & HA_REVERSE_SORT));
12918 }
12919
12920
2/2
✓ Branch 0 taken 979 times.
✓ Branch 1 taken 767 times.
1746 if (ind_type == DICT_SPATIAL) {
12921 979 index->srid_is_valid = has_srid;
12922 979 index->srid = srid;
12923
1/2
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
979 index->rtr_srs.reset(fetch_srs(index->srid));
12924 }
12925
12926
2/4
✓ Branch 0 taken 1746 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1746 times.
✗ Branch 3 not taken.
1746 return convert_error_code_to_mysql(
12927 row_create_index_for_mysql(index, trx, nullptr, nullptr), flags,
12928 1746 nullptr);
12929 }
12930
12931 189956 ind_type = 0;
12932
12933
2/2
✓ Branch 0 taken 118783 times.
✓ Branch 1 taken 71173 times.
189956 if (key_num == form->s->primary_key) {
12934 118783 ind_type |= DICT_CLUSTERED;
12935 }
12936
12937
2/2
✓ Branch 0 taken 152250 times.
✓ Branch 1 taken 37706 times.
189956 if (key->flags & HA_NOSAME) {
12938 152250 ind_type |= DICT_UNIQUE;
12939 }
12940
12941 379912 field_lengths = (ulint *)my_malloc(
12942
1/2
✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
189956 PSI_INSTRUMENT_ME, key->user_defined_key_parts * sizeof *field_lengths,
12943 MYF(MY_FAE));
12944
12945 /* We pass 0 as the space id, and determine at a lower level the space
12946 id where to store the table */
12947
12948 379912 index = dict_mem_index_create(table_name, key->name, 0, ind_type,
12949
1/2
✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
189956 key->user_defined_key_parts);
12950
12951
1/2
✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
189956 innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd);
12952
1/2
✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
189956 dict_table_t *handler = priv->lookup_table_handler(table_name);
12953
12954
2/2
✓ Branch 0 taken 3128 times.
✓ Branch 1 taken 186828 times.
189956 if (handler != nullptr) {
12955 /* This setting will enforce SQL NULL == SQL NULL.
12956 For now this is turned-on for intrinsic tables
12957 only but can be turned on for other tables if needed arises. */
12958 3128 index->nulls_equal = (key->flags & HA_NULL_ARE_EQUAL) ? true : false;
12959
12960 /* Disable use of AHI for intrinsic table indexes as AHI
12961 validates the predicated entry using index-id which has to be
12962 system-wide unique that is not the case with indexes of
12963 intrinsic table for performance reason.
12964 Also given the lifetime of these tables and frequent delete
12965 and update AHI would not help on performance front as it does
12966 with normal tables. */
12967 3128 index->disable_ahi = true;
12968 }
12969
12970
2/2
✓ Branch 0 taken 253708 times.
✓ Branch 1 taken 189956 times.
443664 for (ulint i = 0; i < key->user_defined_key_parts; i++) {
12971 253708 KEY_PART_INFO *key_part = key->key_part + i;
12972 ulint prefix_len;
12973 ulint col_type;
12974 ulint is_unsigned;
12975
12976 /* (The flag HA_PART_KEY_SEG denotes in MySQL a
12977 column prefix field in an index: we only store a
12978 specified number of first bytes of the column to
12979 the index field.) The flag does not seem to be
12980 properly set by MySQL. Let us fall back on testing
12981 the length of the key part versus the column.
12982 We first reach to the table's column; if the index is on a
12983 prefix, key_part->field is not the table's column (it's a
12984 "fake" field forged in open_table_from_share() with length
12985 equal to the length of the prefix); so we have to go to
12986 form->fied. */
12987 253708 Field *field = form->field[key_part->field->field_index()];
12988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 253708 times.
253708 if (field == nullptr) ut_error;
12989
12990 253708 const char *field_name = key_part->field->field_name;
12991
6/8
✓ Branch 0 taken 4034 times.
✓ Branch 1 taken 249674 times.
✓ Branch 2 taken 4034 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4034 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4034 times.
✓ Branch 7 taken 249674 times.
253708 if (handler != nullptr && handler->is_intrinsic()) {
12992
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4034 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4034 times.
4034 ut_ad(!innobase_is_v_fld(key_part->field));
12993 ulint col_no =
12994
2/4
✓ Branch 0 taken 4034 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4034 times.
✗ Branch 3 not taken.
4034 dict_col_get_no(handler->get_col(key_part->field->field_index()));
12995
1/2
✓ Branch 0 taken 4034 times.
✗ Branch 1 not taken.
4034 field_name = handler->get_col_name(col_no);
12996 }
12997
12998
1/2
✓ Branch 0 taken 253708 times.
✗ Branch 1 not taken.
253708 col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field);
12999
13000 /* Multi-value prefix index is not supported. */
13001
7/8
✓ Branch 0 taken 253708 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 253470 times.
✓ Branch 3 taken 238 times.
✓ Branch 4 taken 234377 times.
✓ Branch 5 taken 19093 times.
✓ Branch 6 taken 20040 times.
✓ Branch 7 taken 233668 times.
741555 if (!innobase_is_multi_value_fld(key_part->field) &&
13002 253470 (DATA_LARGE_MTYPE(col_type) ||
13003
3/4
✓ Branch 0 taken 234377 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55329 times.
✓ Branch 3 taken 179048 times.
234377 (key_part->length < field->pack_length() &&
13004
3/4
✓ Branch 0 taken 55329 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54830 times.
✓ Branch 3 taken 499 times.
55329 field->type() != MYSQL_TYPE_VARCHAR) ||
13005
3/4
✓ Branch 0 taken 233878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54830 times.
✓ Branch 3 taken 179048 times.
233878 (field->type() == MYSQL_TYPE_VARCHAR &&
13006 54830 key_part->length <
13007
4/6
✓ Branch 0 taken 54830 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54830 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 448 times.
✓ Branch 5 taken 54382 times.
54830 field->pack_length() - field->get_length_bytes()))) {
13008
1/2
✓ Branch 0 taken 20040 times.
✗ Branch 1 not taken.
20040 switch (col_type) {
13009 20040 default:
13010 20040 prefix_len = key_part->length;
13011 20040 break;
13012 case DATA_INT:
13013 case DATA_FLOAT:
13014 case DATA_DOUBLE:
13015 case DATA_DECIMAL:
13016 log_errlog(ERROR_LEVEL, ER_WRONG_TYPE_FOR_COLUMN_PREFIX_IDX_FLD,
13017 table_name, key_part->field->field_name);
13018
13019 prefix_len = 0;
13020 }
13021 } else {
13022 233668 prefix_len = 0;
13023 }
13024
13025 253708 field_lengths[i] = key_part->length;
13026
13027
7/10
✓ Branch 0 taken 5094 times.
✓ Branch 1 taken 248614 times.
✓ Branch 2 taken 1016 times.
✓ Branch 3 taken 4078 times.
✓ Branch 4 taken 249630 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 249630 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 253708 times.
253708 ut_ad(!(!innobase_is_v_fld(key_part->field) &&
13028 innobase_is_multi_value_fld(key_part->field)));
13029
13030
4/4
✓ Branch 0 taken 5094 times.
✓ Branch 1 taken 248614 times.
✓ Branch 2 taken 4078 times.
✓ Branch 3 taken 1016 times.
253708 if (innobase_is_v_fld(key_part->field)) {
13031 4078 index->type |= DICT_VIRTUAL;
13032
13033
3/4
✓ Branch 0 taken 4078 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 3840 times.
4078 if (innobase_is_multi_value_fld(key_part->field)) {
13034 238 index->type |= DICT_MULTI_VALUE;
13035 }
13036 }
13037
13038 253708 index->add_field(field_name, prefix_len,
13039
1/2
✓ Branch 0 taken 253708 times.
✗ Branch 1 not taken.
253708 !(key_part->key_part_flag & HA_REVERSE_SORT));
13040 }
13041
13042
3/6
✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 189956 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 189956 times.
189956 ut_ad(key->flags & HA_FULLTEXT || !(index->type & DICT_FTS));
13043
13044 189956 multi_val_idx = ((index->type & DICT_MULTI_VALUE) == DICT_MULTI_VALUE);
13045
13046 /* Even though we've defined max_supported_key_part_length, we
13047 still do our own checking using field_lengths to be absolutely
13048 sure we don't create too long indexes. */
13049
13050
2/4
✓ Branch 0 taken 189855 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 189855 times.
✗ Branch 3 not taken.
189956 error = convert_error_code_to_mysql(
13051 row_create_index_for_mysql(index, trx, field_lengths, handler), flags,
13052 nullptr);
13053
13054 /* For multi-value virtual index, we need to adjust indexed col length */
13055
4/4
✓ Branch 0 taken 189841 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 189603 times.
189855 if (error == 0 && multi_val_idx) {
13056
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 dict_table_t *new_table = dd_table_open_on_name_in_mem(table_name, false);
13057
13058 238 dict_index_t *last_index = UT_LIST_GET_LAST(new_table->indexes);
13059
2/2
✓ Branch 0 taken 513 times.
✓ Branch 1 taken 238 times.
751 for (unsigned int i = 0; i < last_index->n_fields; i++) {
13060
4/4
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 275 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 357 times.
751 if (last_index->fields[i].col->is_multi_value() &&
13061
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 82 times.
238 (last_index->fields[i].fixed_len != 0)) {
13062 156 last_index->fields[i].fixed_len = field_lengths[i];
13063 }
13064 }
13065
13066
1/2
✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
238 dd_table_close(new_table, nullptr, nullptr, false);
13067 }
13068
13069
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 189841 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
189855 if (error && handler != nullptr) {
13070 priv->unregister_table_handler(table_name);
13071 }
13072
13073
1/2
✓ Branch 0 taken 189855 times.
✗ Branch 1 not taken.
189855 my_free(field_lengths);
13074
13075 189855 return error;
13076 191602 }
13077
13078 /** Creates an index to an InnoDB table when the user has defined no
13079 primary index. */
13080 310387 inline int create_clustered_index_when_no_primary(
13081 trx_t *trx, /*!< in: InnoDB transaction handle */
13082 uint32_t flags, /*!< in: InnoDB table flags */
13083 const char *table_name) /*!< in: table name */
13084 {
13085 dict_index_t *index;
13086 dberr_t error;
13087
13088 /* We pass 0 as the space id, and determine at a lower level the space
13089 id where to store the table */
13090 310387 index = dict_mem_index_create(table_name, innobase_index_reserve_name, 0,
13091 DICT_CLUSTERED, 0);
13092
13093 310387 innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd);
13094
13095 310387 dict_table_t *handler = priv->lookup_table_handler(table_name);
13096
13097
2/2
✓ Branch 0 taken 181887 times.
✓ Branch 1 taken 128500 times.
310387 if (handler != nullptr) {
13098 /* Disable use of AHI for intrinsic table indexes as AHI
13099 validates the predicated entry using index-id which has to be
13100 system-wide unique that is not the case with indexes of
13101 intrinsic table for performance reason.
13102 Also given the lifetime of these tables and frequent delete
13103 and update AHI would not help on performance front as it does
13104 with normal tables. */
13105 181887 index->disable_ahi = true;
13106 }
13107
13108 310387 error = row_create_index_for_mysql(index, trx, nullptr, handler);
13109
13110
3/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 310362 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
310387 if (error != DB_SUCCESS && handler != nullptr) {
13111 priv->unregister_table_handler(table_name);
13112 }
13113
13114 310387 return (convert_error_code_to_mysql(error, flags, nullptr));
13115 }
13116
13117 26 void create_table_info_t::log_error_invalid_location(std::string &msg,
13118 bool ignore) {
13119
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 18 times.
26 if (ignore) {
13120
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 THD *thd = current_thd;
13121
13122 8 constexpr char ignored_msg[] =
13123 " The DATA DIRECTORY location will be ignored and the"
13124 " file will be put into the default datadir location.";
13125
13126
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 msg.append(ignored_msg);
13127
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_FILE_NAME,
13128 "%s", msg.c_str());
13129
13130
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 ib::warn(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str());
13131 } else {
13132 18 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
13133
13134
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str());
13135 }
13136 26 }
13137
13138 892 bool create_table_info_t::create_option_data_directory_is_valid(bool ignore) {
13139 892 bool is_valid = true;
13140
13141
3/6
✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 892 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 892 times.
892 ut_ad(m_create_info->data_file_name != nullptr &&
13142 *m_create_info->data_file_name != '\0');
13143
13144 /* Use DATA DIRECTORY only with file-per-table. */
13145
3/4
✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 884 times.
892 if (!m_use_shared_space && !m_allow_file_per_table) {
13146
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
13147 "InnoDB: DATA DIRECTORY requires"
13148 " innodb_file_per_table.");
13149 8 is_valid = false;
13150 }
13151
13152 /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */
13153
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 886 times.
892 if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
13154
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
13155 "InnoDB: DATA DIRECTORY cannot be used"
13156 " for TEMPORARY tables.");
13157 6 is_valid = false;
13158 }
13159
13160 /* We checked previously for a conflicting DATA DIRECTORY mixed
13161 with TABLESPACE in create_option_tablespace_is_valid().
13162 An ALTER TABLE statement might have both if it is being moved.
13163 So if m_tablespace is set, don't check the existing data_file_name. */
13164
2/2
✓ Branch 0 taken 206 times.
✓ Branch 1 taken 686 times.
892 if (m_create_info->tablespace != nullptr) {
13165 206 return (is_valid);
13166 }
13167
13168 #ifndef UNIV_HOTBACKUP
13169 /* Validate the directory location. */
13170 686 bool suffixed_table_name = !m_partition;
13171
3/6
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 686 times.
✗ Branch 5 not taken.
686 char *filepath = Fil_path::make(m_create_info->data_file_name, m_table_name,
13172 IBD, suffixed_table_name);
13173
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 size_t dirname_len = dirname_length(filepath);
13174
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 Fil_path dirpath(filepath, dirname_len, true);
13175
13176 /* Do not allow the file to be created in a unique undo directory. */
13177
6/8
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 683 times.
729 if (MySQL_undo_path_is_unique && (MySQL_undo_path.is_same_as(dirpath) ||
13178
3/4
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 40 times.
43 MySQL_undo_path.is_ancestor(dirpath))) {
13179 std::string msg(
13180
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 "The DATA DIRECTORY location cannot be the undo directory.");
13181
13182
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 log_error_invalid_location(msg, ignore);
13183
13184 3 is_valid = false;
13185 3 }
13186
13187 /* Do not allow a file-per-table tablespace in the datadir.
13188 In order to be located in the datadir, one must use a schama name
13189 identical to the datadir directory and the datadir parent must be
13190 used as the DATA DIRECTORY.*/
13191
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 bool in_datadir = MySQL_datadir_path.is_same_as(dirpath);
13192
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 684 times.
686 if (in_datadir) {
13193
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 std::string msg("The DATA DIRECTORY location cannot be the datadir.");
13194
13195
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 log_error_invalid_location(msg, ignore);
13196
13197 2 is_valid = false;
13198 2 }
13199
13200 /* Do not allow a datafile outside the known directories. */
13201
1/2
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
686 bool under_datadir = MySQL_datadir_path.is_ancestor(dirpath);
13202 bool in_known_location =
13203
6/8
✓ Branch 0 taken 684 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 684 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 684 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 663 times.
✓ Branch 7 taken 21 times.
686 (in_datadir || under_datadir) ? true : fil_path_is_known(dirpath.path());
13204
13205
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 665 times.
686 if (!in_known_location) {
13206 std::string msg(
13207
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 "The DATA DIRECTORY location must be in a known directory.");
13208
13209
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 log_error_invalid_location(msg, ignore);
13210
13211 21 is_valid = false;
13212 21 }
13213
13214 686 ut::free(filepath);
13215 #endif /* UNIV_HOTBACKUP */
13216
13217 686 return (is_valid);
13218 686 }
13219
13220 /** Validate the tablespace name provided for a tablespace DDL
13221 @param[in] ts_command tablespace command type
13222 @param[in] name A proposed tablespace name
13223 @return MySQL handler error code like HA_... */
13224 501694 static int validate_tablespace_name(ts_command_type ts_command,
13225 const char *name) {
13226 501694 int err = 0;
13227
13228 /* This prefix is reserved by InnoDB for use in internal tablespace
13229 names. */
13230 501694 const char reserved_space_name_prefix[] = "innodb_";
13231
13232 /* Validation at the SQL layer should already be completed at this
13233 stage. Re-assert that the length is valid. */
13234
2/4
✓ Branch 0 taken 501694 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 501694 times.
501694 if (validate_tablespace_name_length(name)) {
13235 my_printf_error(ER_WRONG_TABLESPACE_NAME,
13236 "InnoDB: Tablespace name `%s` is too long.", MYF(0), name);
13237 return (HA_WRONG_CREATE_OPTION);
13238 }
13239
13240 /* The tablespace name cannot start with `innodb_`. */
13241
2/2
✓ Branch 0 taken 22006 times.
✓ Branch 1 taken 479688 times.
501694 if (strlen(name) >= sizeof(reserved_space_name_prefix) - 1 &&
13242
2/2
✓ Branch 0 taken 2058 times.
✓ Branch 1 taken 19948 times.
22006 0 == memcmp(name, reserved_space_name_prefix,
13243 sizeof(reserved_space_name_prefix) - 1)) {
13244 /* Use a different message for reserved names */
13245
2/2
✓ Branch 0 taken 1070 times.
✓ Branch 1 taken 988 times.
2058 if (0 == strcmp(name, dict_sys_t::s_file_per_table_name) ||
13246
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 762 times.
1070 0 == strcmp(name, dict_sys_t::s_sys_space_name) ||
13247
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 271 times.
308 0 == strcmp(name, dict_sys_t::s_temp_space_name)) {
13248 /* Allow these names if the caller is putting a
13249 table into one of these by CREATE/ALTER TABLE */
13250
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1770 times.
1787 if (ts_command != TS_CMD_NOT_DEFINED) {
13251
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 my_printf_error(ER_WRONG_TABLESPACE_NAME,
13252 "InnoDB: `%s` is a reserved"
13253 " tablespace name.",
13254 MYF(0), name);
13255 17 err = HA_WRONG_CREATE_OPTION;
13256 }
13257 } else {
13258 /* Allow any undo tablespace to be set active or inactive.
13259 And any undo tablespace can be dropped except the default two
13260 implicit spaces. All other DDL should not work on tablespaces
13261 that start with "innodb_". */
13262 271 bool allow =
13263
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 20 times.
278 (ts_command == ALTER_UNDO_TABLESPACE ||
13264 7 (ts_command == DROP_UNDO_TABLESPACE &&
13265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_1) &&
13266 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_2)));
13267
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
271 if (!allow) {
13268
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_printf_error(ER_WRONG_TABLESPACE_NAME,
13269 "InnoDB: Tablespace names starting"
13270 " with `%s` are reserved.",
13271 MYF(0), reserved_space_name_prefix);
13272 27 err = HA_WRONG_CREATE_OPTION;
13273 }
13274 }
13275
2/2
✓ Branch 0 taken 473445 times.
✓ Branch 1 taken 26191 times.
501694 } else if (0 == strcmp(name, dict_sys_t::s_dd_space_name)) {
13276 /* mysql tablespace can't be created or dropped */
13277
4/4
✓ Branch 0 taken 473441 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 473434 times.
473445 if (ts_command == CREATE_TABLESPACE || ts_command == DROP_TABLESPACE) {
13278
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_printf_error(ER_WRONG_TABLESPACE_NAME,
13279 "InnoDB: `mysql` is a reserved"
13280 " tablespace name.",
13281 MYF(0));
13282 11 err = HA_WRONG_CREATE_OPTION;
13283 }
13284 }
13285
13286 /* The tablespace name cannot contain a '/'. */
13287
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 501687 times.
501694 if (memchr(name, '/', strlen(name)) != nullptr) {
13288
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(ER_WRONG_TABLESPACE_NAME,
13289 "InnoDB: A general tablespace name cannot"
13290 " contain '/'.",
13291 MYF(0));
13292 7 err = HA_WRONG_CREATE_OPTION;
13293 }
13294
13295 501694 return (err);
13296 }
13297
13298 441225 bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd,
13299 const char *name) {
13300 441225 return (0 == validate_tablespace_name(ts_cmd, name));
13301 }
13302
13303 /** Validate TABLESPACE option.
13304 @return true if valid, false if not. */
13305 458916 bool create_table_info_t::create_option_tablespace_is_valid() {
13306 458916 bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
13307 458916 bool is_file_per_table = tablespace_is_file_per_table(m_create_info);
13308 458916 bool is_general_space = tablespace_is_general_space(m_create_info);
13309 458916 bool is_temp_space =
13310
2/2
✓ Branch 0 taken 68805 times.
✓ Branch 1 taken 390111 times.
527721 (m_create_info->tablespace &&
13311
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 68788 times.
68805 strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0);
13312
13313 /* Do not allow creation of a temp table
13314 with innodb_file_per_table or innodb_temporary option. */
13315
6/6
✓ Branch 0 taken 228908 times.
✓ Branch 1 taken 230008 times.
✓ Branch 2 taken 228906 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 228893 times.
458916 if (is_temp && (is_file_per_table || is_temp_space)) {
13316
7/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 14 times.
15 if (THDVAR(m_thd, strict_mode) && is_file_per_table) {
13317 1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13318 "InnoDB: TABLESPACE=%s option"
13319 " is disallowed for temporary tables"
13320 " with INNODB_STRICT_MODE=ON. This option is"
13321 " deprecated and will be removed in a future release",
13322
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 MYF(0), m_create_info->tablespace);
13323 1 return false;
13324 }
13325
13326 /* STRICT mode turned off. Proceed with the execution with
13327 a deprecation warning */
13328 14 push_warning_printf(
13329 m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
13330 "InnoDB: TABLESPACE=%s option is ignored. All temporary tables"
13331 " are created in a session temporary tablespace. This option"
13332 " is deprecated and will be removed in a future release.",
13333
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 m_create_info->tablespace);
13334 }
13335
13336 /* Check the encryption option validity. */
13337
6/6
✓ Branch 0 taken 105443 times.
✓ Branch 1 taken 353472 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 105397 times.
✓ Branch 4 taken 46 times.
✓ Branch 5 taken 458869 times.
564358 if (m_create_info->encrypt_type.str != nullptr &&
13338 105443 Encryption::validate(m_create_info->encrypt_type.str) == DB_UNSUPPORTED) {
13339
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
13340 46 return false;
13341 }
13342
13343
2/2
✓ Branch 0 taken 412851 times.
✓ Branch 1 taken 46018 times.
458869 if (!m_use_shared_space) {
13344
2/2
✓ Branch 0 taken 233418 times.
✓ Branch 1 taken 179433 times.
412851 if (!m_use_file_per_table) {
13345
2/2
✓ Branch 0 taken 1157 times.
✓ Branch 1 taken 232261 times.
233418 if (m_create_info->encrypt_type.str != nullptr &&
13346
4/4
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1101 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 11 times.
1157 m_create_info->explicit_encryption && is_temp) {
13347 /* Temporary tablespace is being used for table */
13348
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13349 "InnoDB: ENCRYPTION is not accepted"
13350 " for temporary tablespace. For temporary tablespace"
13351 " encryption please use innodb_temp_tablespace_encrypt"
13352 " variable.",
13353 MYF(0));
13354 45 return false;
13355 }
13356
13357
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 233372 times.
233373 if (m_create_info->m_implicit_tablespace_autoextend_size > 0) {
13358 /* AUTOEXTEND_SIZE is not allowed for system tablespace. */
13359
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13360 "InnoDB : AUTOEXTEND_SIZE is not accepted"
13361 " for system tablespace.",
13362 MYF(0));
13363 1 return false;
13364 }
13365 }
13366
13367 /* Validate autoextend_size attribute value. */
13368
4/4
✓ Branch 0 taken 5425 times.
✓ Branch 1 taken 407380 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 412791 times.
418230 if (m_create_info->m_implicit_tablespace_autoextend_size > 0 &&
13369
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5411 times.
5425 validate_autoextend_size_value(
13370
1/2
✓ Branch 0 taken 5425 times.
✗ Branch 1 not taken.
5425 m_create_info->m_implicit_tablespace_autoextend_size) !=
13371 DB_SUCCESS) {
13372 14 return false;
13373 }
13374 412791 return true;
13375 }
13376
13377
3/4
✓ Branch 0 taken 46018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✓ Branch 3 taken 45639 times.
46018 if (m_use_shared_space && !is_general_space) {
13378
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 147 times.
379 if (m_create_info->m_implicit_tablespace_autoextend_size_change &&
13379
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 231 times.
232 m_create_info->m_implicit_tablespace_autoextend_size > 0) {
13380 /* AUTOEXTEND_SIZE is not allowed for system tablespace. */
13381
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13382 "InnoDB : AUTOEXTEND_SIZE is not accepted"
13383 " for system tablespace.",
13384 MYF(0));
13385 1 return false;
13386 }
13387 }
13388
13389 /* ALTER TABLE ... AUTOEXTEND_SIZE is not allowed if the tablespace is
13390 a general tablespace. */
13391
5/6
✓ Branch 0 taken 45998 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 45634 times.
✓ Branch 3 taken 364 times.
✓ Branch 4 taken 45634 times.
✗ Branch 5 not taken.
46017 if (!is_temp && is_general_space && m_use_shared_space) {
13392
2/2
✓ Branch 0 taken 28139 times.
✓ Branch 1 taken 17495 times.
45634 if (m_create_info->m_implicit_tablespace_autoextend_size_change &&
13393
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 28133 times.
28139 m_create_info->m_implicit_tablespace_autoextend_size > 0) {
13394
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_INNODB_INCOMPATIBLE_WITH_TABLESPACE, MYF(0),
13395 "AUTOEXTEND_SIZE");
13396 6 return false;
13397 }
13398 }
13399
13400 /* Validate autoextend_size attribute value. */
13401
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 46009 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46011 times.
46013 if (m_create_info->m_implicit_tablespace_autoextend_size > 0 &&
13402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 validate_autoextend_size_value(
13403
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 m_create_info->m_implicit_tablespace_autoextend_size) != DB_SUCCESS) {
13404 return false;
13405 }
13406
13407 /* Name validation should be ensured from the SQL layer. */
13408
2/4
✓ Branch 0 taken 46011 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46011 times.
46011 ut_ad(0 == validate_tablespace_name(TS_CMD_NOT_DEFINED,
13409 m_create_info->tablespace));
13410
13411 /* Look up the tablespace name in the fil_system. */
13412
1/2
✓ Branch 0 taken 46011 times.
✗ Branch 1 not taken.
46011 space_id_t space_id = fil_space_get_id_by_name(m_create_info->tablespace);
13413
13414
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 46009 times.
46011 if (space_id == SPACE_UNKNOWN) {
13415 2 my_printf_error(ER_TABLESPACE_MISSING,
13416 "InnoDB: A general tablespace named"
13417 " `%s` cannot be found.",
13418
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 MYF(0), m_create_info->tablespace);
13419 2 return false;
13420 }
13421
13422
3/4
✓ Branch 0 taken 46009 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 46007 times.
46009 if (fsp_is_undo_tablespace(space_id)) {
13423
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_WRONG_TABLESPACE_NAME,
13424 "InnoDB: An undo tablespace cannot contain tables.",
13425 MYF(0));
13426
13427 2 return false;
13428 }
13429
13430 /* Cannot add a second table to a file-per-table tablespace. */
13431
1/2
✓ Branch 0 taken 46007 times.
✗ Branch 1 not taken.
46007 uint32_t fsp_flags = fil_space_get_flags(space_id);
13432
2/4
✓ Branch 0 taken 46007 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46007 times.
46007 if (fsp_is_file_per_table(space_id, fsp_flags)) {
13433 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13434 "InnoDB: Tablespace `%s` is file-per-table so no"
13435 " other table can be added to it.",
13436 MYF(0), m_create_info->tablespace);
13437 return false;
13438 }
13439
13440
1/2
✓ Branch 0 taken 46007 times.
✗ Branch 1 not taken.
46007 bool is_create_table = (thd_sql_command(m_thd) == SQLCOM_CREATE_TABLE);
13441
13442 /* If TABLESPACE=innodb_file_per_table this function is not called
13443 since tablespace_is_shared_space() will return false. Any other
13444 tablespace is incompatible with the DATA DIRECTORY phrase.
13445 On any ALTER TABLE that contains a DATA DIRECTORY, MySQL will issue
13446 a warning like "<DATA DIRECTORY> option ignored." The check below is
13447 needed for CREATE TABLE only. ALTER TABLE may be moving remote
13448 file-per-table table to a general tablespace, in which case the
13449 create_info->data_file_name is not null. */
13450
4/4
✓ Branch 0 taken 26611 times.
✓ Branch 1 taken 19396 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 26609 times.
46007 if (is_create_table && m_create_info->data_file_name != nullptr &&
13451
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 *m_create_info->data_file_name != '\0') {
13452
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13453 "InnoDB: DATA DIRECTORY cannot be used"
13454 " with a TABLESPACE assignment.",
13455 MYF(0));
13456 2 return false;
13457 }
13458
13459 /* Temp tables only belong in temp tablespaces. */
13460
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 45986 times.
46005 if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
13461
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 if (!FSP_FLAGS_GET_TEMPORARY(fsp_flags)) {
13462 6 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13463 "InnoDB: Tablespace `%s` cannot contain"
13464 " TEMPORARY tables.",
13465
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 MYF(0), m_create_info->tablespace);
13466 6 return false;
13467 }
13468
13469 /* Restrict Compressed Temporary General tablespaces. */
13470
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (m_create_info->key_block_size ||
13471
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 m_create_info->row_type == ROW_TYPE_COMPRESSED) {
13472 1 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13473 "InnoDB: Temporary tablespace `%s` cannot"
13474 " contain COMPRESSED tables.",
13475
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 MYF(0), m_create_info->tablespace);
13476 1 return false;
13477 }
13478
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 45982 times.
45986 } else if (FSP_FLAGS_GET_TEMPORARY(fsp_flags)) {
13479 4 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13480 "InnoDB: Tablespace `%s` can only contain"
13481 " TEMPORARY tables.",
13482
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 MYF(0), m_create_info->tablespace);
13483 4 return false;
13484 }
13485
13486 /* Make sure the physical page size of the table matches the
13487 file block size of the tablespace. */
13488 ulint block_size_needed;
13489 bool table_is_compressed;
13490
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 45748 times.
45994 if (m_create_info->key_block_size) {
13491 246 block_size_needed = m_create_info->key_block_size * 1024;
13492 246 table_is_compressed = true;
13493
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 45740 times.
45748 } else if (m_create_info->row_type == ROW_TYPE_COMPRESSED) {
13494 8 block_size_needed =
13495 8 std::min(UNIV_PAGE_SIZE / 2, static_cast<ulint>(UNIV_ZIP_SIZE_MAX));
13496 8 table_is_compressed = true;
13497 } else {
13498 45740 block_size_needed = UNIV_PAGE_SIZE;
13499 45740 table_is_compressed = false;
13500 }
13501
13502
1/2
✓ Branch 0 taken 45994 times.
✗ Branch 1 not taken.
45994 const page_size_t page_size(fsp_flags);
13503
13504 /* The compression code needs some work in order for a general
13505 tablespace to contain both compressed and non-compressed tables
13506 together in the same tablespace. The problem seems to be that
13507 each page is either compressed or not based on the fsp flags,
13508 which is shared by all tables in that general tablespace. */
13509
7/8
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 45740 times.
✓ Branch 2 taken 254 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✓ Branch 5 taken 185 times.
✓ Branch 6 taken 69 times.
✓ Branch 7 taken 45925 times.
45994 if (table_is_compressed && page_size.physical() == UNIV_PAGE_SIZE) {
13510 69 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13511 "InnoDB: Tablespace `%s` cannot contain a"
13512 " COMPRESSED table",
13513
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 MYF(0), m_create_info->tablespace);
13514 69 return false;
13515 }
13516
13517
3/4
✓ Branch 0 taken 45925 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✓ Branch 3 taken 45775 times.
45925 if (block_size_needed != page_size.physical()) {
13518
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13519 "InnoDB: Tablespace `%s` uses block size %zu"
13520 " and cannot contain a table with physical"
13521 " page size " ULINTPF,
13522
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 MYF(0), m_create_info->tablespace, page_size.physical(),
13523 block_size_needed);
13524 150 return false;
13525 }
13526
13527 45775 return true;
13528 }
13529
13530 /** Validate the COPMRESSION option.
13531 @return true if valid, false if not. */
13532 835314 bool create_table_info_t::create_option_compression_is_valid() {
13533 dberr_t err;
13534 835314 Compression compression;
13535
13536
2/2
✓ Branch 0 taken 834836 times.
✓ Branch 1 taken 480 times.
835316 if (m_create_info->compress.length == 0) {
13537 834836 return (true);
13538 }
13539
13540
1/2
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
480 err = Compression::check(m_create_info->compress.str, &compression);
13541
13542
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 473 times.
479 if (err == DB_UNSUPPORTED) {
13543 6 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13544 ER_UNSUPPORTED_EXTENSION,
13545 "InnoDB: Unsupported compression algorithm '%s'",
13546
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 m_create_info->compress.str);
13547 6 return (false);
13548 }
13549
13550 /* Allow Compression=NONE on any tablespace or row format. */
13551
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 387 times.
473 if (compression.m_type == Compression::NONE) {
13552 86 return (true);
13553 }
13554
13555 static char intro[] = "InnoDB: Page Compression is not supported";
13556
13557
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 4 times.
387 if (m_create_info->key_block_size != 0 ||
13558
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 377 times.
383 m_create_info->row_type == ROW_TYPE_COMPRESSED) {
13559
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13560 ER_UNSUPPORTED_EXTENSION,
13561 "%s with row_format=compressed or"
13562 " key_block_size > 0",
13563 intro);
13564 10 return (false);
13565 }
13566
13567
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 372 times.
377 if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
13568
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
13569 "%s for temporary tables", intro);
13570 5 return (false);
13571 }
13572
13573
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 366 times.
372 if (tablespace_is_general_space(m_create_info)) {
13574
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
13575 "%s for shared general tablespaces", intro);
13576 6 return (false);
13577 }
13578
13579 /* The only non-file-per-table tablespace left is the system space. */
13580
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 341 times.
366 if (!m_use_file_per_table) {
13581
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED,
13582 "%s for the system tablespace", intro);
13583 25 return (false);
13584 }
13585
13586 341 return (true);
13587 }
13588
13589 /** Validate ENCRYPTION option.
13590 @return true if valid, false if not. */
13591 458566 bool create_table_info_t::create_option_encryption_is_valid() const {
13592
2/2
✓ Branch 0 taken 105219 times.
✓ Branch 1 taken 353347 times.
458566 if (m_create_info->encrypt_type.length > 0) {
13593 105219 dberr_t err = Encryption::validate(m_create_info->encrypt_type.str);
13594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105220 times.
105220 if (err == DB_UNSUPPORTED) {
13595 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
13596 return (false);
13597 }
13598 }
13599
13600 bool table_is_keyring =
13601 458567 Encryption::is_keyring(m_create_info->encrypt_type.str);
13602
13603
3/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 458490 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
458567 if (table_is_keyring && !m_allow_file_per_table) {
13604 my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
13605 "InnoDB: KEYRING requires innodb_file_per_table.", MYF(0));
13606 return (false);
13607 }
13608
13609
2/2
✓ Branch 0 taken 4902 times.
✓ Branch 1 taken 453588 times.
458490 if (!table_is_keyring &&
13610
4/6
✓ Branch 0 taken 458490 times.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4902 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 458567 times.
917057 Encryption::is_master_key_encryption(m_create_info->encrypt_type.str) &&
13611 4902 Encryption::is_online_encryption_on()) {
13612 my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
13613 "InnoDB: ENCRYPTED='Y' not supported for table because "
13614 "online encryption to KEYRING is turned ON.",
13615 MYF(0));
13616 return (false);
13617 }
13618
13619 /* Currently we do not support keyring encryption for
13620 spatial indexes thus do not allow creating table with forced
13621 encryption */
13622
13623
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 458482 times.
458567 if (Encryption::should_be_keyring_encrypted(
13624 458567 m_create_info->explicit_encryption,
13625 458567 m_create_info->encrypt_type.str)) {
13626
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 85 times.
126 for (ulint i = 0; i < m_form->s->keys; i++) {
13627 41 const KEY *key = m_form->key_info + i;
13628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (key->flags & HA_SPATIAL) {
13629 my_printf_error(
13630 ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
13631 "InnoDB: ENCRYPTED='KEYRING' not supported for table because "
13632 "it contains spatial index.",
13633 MYF(0));
13634 return (false);
13635 }
13636 }
13637 }
13638
13639 const bool table_is_encrypted =
13640 458567 !Encryption::is_none(m_create_info->encrypt_type.str);
13641
13642 ulint space_id;
13643
2/2
✓ Branch 0 taken 45775 times.
✓ Branch 1 taken 412792 times.
458567 if (m_use_shared_space) {
13644 45775 space_id = fil_space_get_id_by_name(m_create_info->tablespace);
13645
2/2
✓ Branch 0 taken 228843 times.
✓ Branch 1 taken 183949 times.
412792 } else if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
13646 228843 space_id = srv_tmp_space.space_id();
13647
2/2
✓ Branch 0 taken 4529 times.
✓ Branch 1 taken 179420 times.
183949 } else if (!m_use_file_per_table) {
13648 4529 space_id = TRX_SYS_SPACE;
13649 } else {
13650 179420 return (true);
13651 }
13652
13653 279147 fil_space_t *space = fil_space_get(space_id);
13654 279147 const auto fsp_flags = space->flags;
13655
13656 279147 const bool tablespace_is_encrypted = FSP_FLAGS_GET_ENCRYPTION(fsp_flags);
13657 279147 const char *const tablespace_name =
13658
2/2
✓ Branch 0 taken 48863 times.
✓ Branch 1 taken 230284 times.
279147 m_create_info->tablespace ? m_create_info->tablespace : space->name;
13659
13660
3/4
✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 277893 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1254 times.
279147 if (table_is_encrypted && !tablespace_is_encrypted) {
13661 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
13662 "InnoDB: Tablespace `%s` cannot contain an"
13663 " ENCRYPTED table.",
13664 MYF(0), tablespace_name);
13665 return (false);
13666 }
13667
13668 279147 return (true);
13669 }
13670
13671 /** Validate the create options. Check that the options KEY_BLOCK_SIZE,
13672 ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE are compatible with
13673 each other and other settings. These CREATE OPTIONS are not validated
13674 here unless innodb_strict_mode is on. With strict mode, this function
13675 will report each problem it finds using a custom message with error
13676 code ER_ILLEGAL_HA_CREATE_OPTION, not its built-in message.
13677 @return NULL if valid, string name of bad option if not. */
13678 458916 const char *create_table_info_t::create_options_are_invalid() {
13679 458916 bool has_key_block_size = (m_create_info->key_block_size != 0);
13680 458916 bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
13681
13682 458916 const char *ret = nullptr;
13683 458916 enum row_type row_format = m_create_info->row_type;
13684
13685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458917 times.
458916 ut_ad(m_thd != nullptr);
13686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458917 times.
458917 ut_ad(m_create_info != nullptr);
13687
13688 /* The TABLESPACE designation on a CREATE TABLE is not subject to
13689 non-strict-mode. If it is incorrect or is incompatible with other
13690 options, then we will return an error. Make sure the tablespace exists
13691 and is compatible with this table */
13692
2/2
✓ Branch 0 taken 350 times.
✓ Branch 1 taken 458566 times.
458917 if (!create_option_tablespace_is_valid()) {
13693 350 return ("TABLESPACE");
13694 }
13695
13696 /* Validate encryption parameter even if strict_mode is OFF. */
13697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458567 times.
458566 if (!create_option_encryption_is_valid()) return ("ENCRYPTION");
13698
13699 /* If innodb_strict_mode is not set don't do any more validation.
13700 Also, if this table is being put into a shared general tablespace
13701 we ALWAYS act like strict mode is ON.
13702 Or if caller explicitly asks for skipping strict mode check (if
13703 tablespace is not a shared general tablespace), then skip */
13704
8/8
✓ Branch 0 taken 412792 times.
✓ Branch 1 taken 45775 times.
✓ Branch 2 taken 411491 times.
✓ Branch 3 taken 1301 times.
✓ Branch 4 taken 50321 times.
✓ Branch 5 taken 361170 times.
✓ Branch 6 taken 51622 times.
✓ Branch 7 taken 406945 times.
458567 if (!m_use_shared_space && (!(THDVAR(m_thd, strict_mode)) || skip_strict())) {
13705 51622 return (nullptr);
13706 }
13707
13708 /* Check if a non-zero KEY_BLOCK_SIZE was specified. */
13709
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 406561 times.
406945 if (has_key_block_size) {
13710
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 374 times.
384 if (is_temp) {
13711 10 my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0));
13712 10 return ("KEY_BLOCK_SIZE");
13713 }
13714
13715
2/2
✓ Branch 0 taken 365 times.
✓ Branch 1 taken 9 times.
374 switch (m_create_info->key_block_size) {
13716 ulint kbs_max;
13717 365 case 1:
13718 case 2:
13719 case 4:
13720 case 8:
13721 case 16:
13722 /* The maximum KEY_BLOCK_SIZE (KBS) is
13723 UNIV_PAGE_SIZE_MAX. But if UNIV_PAGE_SIZE is
13724 smaller than UNIV_PAGE_SIZE_MAX, the maximum
13725 KBS is also smaller. */
13726 730 kbs_max = std::min(1 << (UNIV_PAGE_SSIZE_MAX - 1),
13727 365 1 << (PAGE_ZIP_SSIZE_MAX - 1));
13728
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 356 times.
365 if (m_create_info->key_block_size > kbs_max) {
13729 9 push_warning_printf(
13730 m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
13731 "InnoDB: KEY_BLOCK_SIZE=%" PRIu32 " cannot be larger than %ld.",
13732 9 m_create_info->key_block_size, kbs_max);
13733 9 ret = "KEY_BLOCK_SIZE";
13734 }
13735
13736 /* The following checks do not appy to shared tablespaces */
13737
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 305 times.
365 if (m_use_shared_space) {
13738 60 break;
13739 }
13740
13741 /* Valid KEY_BLOCK_SIZE, check its dependencies. */
13742
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 294 times.
305 if (!m_allow_file_per_table) {
13743 11 push_warning(m_thd, Sql_condition::SL_WARNING,
13744 ER_ILLEGAL_HA_CREATE_OPTION,
13745 "InnoDB: KEY_BLOCK_SIZE requires"
13746 " innodb_file_per_table.");
13747 11 ret = "KEY_BLOCK_SIZE";
13748 }
13749 305 break;
13750 9 default:
13751 9 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13752 ER_ILLEGAL_HA_CREATE_OPTION,
13753 "InnoDB: invalid KEY_BLOCK_SIZE = %" PRIu32
13754 ". Valid values are [1, 2, 4, 8, 16]",
13755 9 m_create_info->key_block_size);
13756 9 ret = "KEY_BLOCK_SIZE";
13757 9 break;
13758 }
13759 }
13760
13761 /* Check for a valid InnoDB ROW_FORMAT specifier and
13762 other incompatibilities. */
13763
5/5
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 39952 times.
✓ Branch 2 taken 366573 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 1 times.
406935 switch (row_format) {
13764 402 case ROW_TYPE_COMPRESSED:
13765
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 379 times.
402 if (is_temp) {
13766 23 my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0));
13767 23 return ("ROW_FORMAT");
13768 }
13769
4/4
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 341 times.
379 if (!m_use_shared_space && !m_allow_file_per_table) {
13770 2 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13771 ER_ILLEGAL_HA_CREATE_OPTION,
13772 "InnoDB: %s requires innodb_file_per_table.",
13773 get_row_format_name(row_format));
13774 2 ret = "ROW_FORMAT";
13775 }
13776 379 break;
13777 39952 case ROW_TYPE_DYNAMIC:
13778 case ROW_TYPE_COMPACT:
13779 case ROW_TYPE_REDUNDANT:
13780
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 39930 times.
39952 if (has_key_block_size) {
13781 22 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13782 ER_ILLEGAL_HA_CREATE_OPTION,
13783 "InnoDB: cannot specify %s"
13784 " with KEY_BLOCK_SIZE.",
13785 get_row_format_name(row_format));
13786 22 ret = "KEY_BLOCK_SIZE";
13787 }
13788 39952 break;
13789 366573 case ROW_TYPE_DEFAULT:
13790 366573 break;
13791 7 case ROW_TYPE_FIXED:
13792 case ROW_TYPE_PAGED:
13793 case ROW_TYPE_NOT_USED:
13794 7 push_warning(m_thd, Sql_condition::SL_WARNING,
13795 ER_ILLEGAL_HA_CREATE_OPTION,
13796 "InnoDB: invalid ROW_FORMAT specifier.");
13797 7 ret = "ROW_TYPE";
13798 7 break;
13799 }
13800
13801 832916 if (m_create_info->data_file_name != nullptr &&
13802
8/8
✓ Branch 0 taken 19092 times.
✓ Branch 1 taken 387820 times.
✓ Branch 2 taken 497 times.
✓ Branch 3 taken 18595 times.
✓ Branch 4 taken 417 times.
✓ Branch 5 taken 80 times.
✓ Branch 6 taken 25 times.
✓ Branch 7 taken 406887 times.
407329 *m_create_info->data_file_name != '\0' && m_table_name != nullptr &&
13803
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 392 times.
417 !create_option_data_directory_is_valid()) {
13804 25 ret = "DATA DIRECTORY";
13805 }
13806
13807 /* Do not allow INDEX_DIRECTORY */
13808
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 406908 times.
406912 if (m_create_info->index_file_name) {
13809 4 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
13810 ER_ILLEGAL_HA_CREATE_OPTION,
13811 "InnoDB: INDEX DIRECTORY is not supported");
13812 4 ret = "INDEX DIRECTORY";
13813 }
13814
13815 /* Don't support compressed table when page size > 16k. */
13816
4/4
✓ Branch 0 taken 406537 times.
✓ Branch 1 taken 375 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 406381 times.
406912 if ((has_key_block_size || row_format == ROW_TYPE_COMPRESSED) &&
13817
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 518 times.
531 UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) {
13818 13 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
13819 "InnoDB: Cannot create a COMPRESSED table"
13820 " when innodb_page_size > 16k.");
13821
13822
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 if (has_key_block_size) {
13823 8 ret = "KEY_BLOCK_SIZE";
13824 } else {
13825 5 ret = "ROW_TYPE";
13826 }
13827 }
13828
13829 /* Validate the page compression parameter. */
13830
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 406869 times.
406912 if (!create_option_compression_is_valid()) {
13831 42 return ("COMPRESSION");
13832 }
13833
13834 /* Check the encryption option. */
13835
4/4
✓ Branch 0 taken 406778 times.
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 54495 times.
✓ Branch 3 taken 352283 times.
406869 if (ret == nullptr && m_create_info->encrypt_type.str != nullptr) {
13836 dberr_t err;
13837
13838 54495 err = Encryption::validate(m_create_info->encrypt_type.str);
13839
13840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54496 times.
54495 if (err == DB_UNSUPPORTED) {
13841 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
13842 ret = "ENCRYPTION";
13843 }
13844 }
13845
13846 406870 return (ret);
13847 }
13848
13849 226313 void ha_innobase::adjust_encryption_key_id(HA_CREATE_INFO *create_info,
13850 dd::Properties *options) noexcept {
13851
2/2
✓ Branch 0 taken 226310 times.
✓ Branch 1 taken 3 times.
226313 if (false == create_info->was_encryption_key_id_set) {
13852
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 226231 times.
226310 if (Encryption::should_be_keyring_encrypted(
13853 226310 create_info->explicit_encryption, create_info->encrypt_type.str)) {
13854 79 create_info->encryption_key_id =
13855 79 THDVAR(current_thd, default_encryption_key_id);
13856 }
13857 } else {
13858
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (options && (create_info->tablespace == nullptr ||
13859 strcmp(create_info->tablespace,
13860 dict_sys_t::s_file_per_table_name) == 0)) {
13861 3 options->set("encryption_key_id", create_info->encryption_key_id);
13862 }
13863
13864
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
6 if (Encryption::is_master_key_encryption(create_info->encrypt_type.str) ||
13865 3 Encryption::none_explicitly_specified(create_info->explicit_encryption,
13866 3 create_info->encrypt_type.str)) {
13867 // if it is encrypted table with Master key encryption or marked as not to
13868 // be encrypted and alter table does not have ENCRYPTION_KEY_ID - mark
13869 // encryption key id as not set.
13870
13871 push_warning_printf(
13872 current_thd, Sql_condition::SL_WARNING, HA_WRONG_CREATE_OPTION,
13873 Encryption::none_explicitly_specified(
13874 create_info->explicit_encryption, create_info->encrypt_type.str)
13875 ? "InnoDB: Ignored ENCRYPTION_KEY_ID %u when "
13876 "encryption is disabled."
13877 : "InnoDB: Ignored ENCRYPTION_KEY_ID %u when "
13878 "Master Key encryption is enabled.",
13879 create_info->encryption_key_id);
13880 create_info->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY;
13881 create_info->was_encryption_key_id_set = false;
13882 options->remove("encryption_key_id");
13883 }
13884 }
13885 226313 }
13886
13887 /** Adjust encryption options.
13888 @param[in,out] create_info Additional create information.
13889 @param[in,out] table_def dd::Table object to be modified.*/
13890 407290 void ha_innobase::adjust_encryption_options(HA_CREATE_INFO *create_info,
13891 dd::Table *table_def) noexcept {
13892 407290 bool is_intrinsic =
13893 407290 (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) != 0;
13894
13895
2/2
✓ Branch 0 taken 182646 times.
✓ Branch 1 taken 224644 times.
407290 if (is_intrinsic) {
13896 182646 return;
13897 }
13898
13899 #ifdef UNIV_DEBUG
13900 // check that create_info->explicit_encryption is in sync with
13901 // DD's explicit_encryption
13902
2/2
✓ Branch 0 taken 19877 times.
✓ Branch 1 taken 204767 times.
224644 if (create_info->explicit_encryption) {
13903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19877 times.
19877 ut_ad(table_def->options().exists("explicit_encryption"));
13904 19877 bool explicit_encryption{false};
13905 19877 table_def->options().get("explicit_encryption", &explicit_encryption);
13906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19877 times.
19877 ut_ad(explicit_encryption);
13907 }
13908 #endif /* UNIV_DEBUG */
13909
13910 224644 bool is_tmp = (create_info->options & HA_LEX_CREATE_TMP_TABLE) != 0;
13911
13912
2/2
✓ Branch 0 taken 46221 times.
✓ Branch 1 taken 178423 times.
224644 if (is_tmp) {
13913 46221 return;
13914 }
13915
13916
1/2
✓ Branch 0 taken 178423 times.
✗ Branch 1 not taken.
356846 adjust_encryption_key_id(create_info,
13917 178423 table_def ? &(table_def->options()) : nullptr);
13918 }
13919
13920 /** Update create_info. Used in SHOW CREATE TABLE et al. */
13921
13922 101119 void ha_innobase::update_create_info(
13923 HA_CREATE_INFO *create_info) /*!< in/out: create info */
13924 {
13925
2/2
✓ Branch 0 taken 100946 times.
✓ Branch 1 taken 173 times.
101119 if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
13926 100946 info(HA_STATUS_AUTO);
13927 100946 create_info->auto_increment_value = stats.auto_increment_value;
13928 }
13929
13930 /* Update the DATA DIRECTORY name. */
13931 101119 dd_get_and_save_data_dir_path<dd::Table>(m_prebuilt->table, nullptr, false);
13932
13933
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 100924 times.
101119 if (m_prebuilt->table->data_dir_path != nullptr) {
13934 195 create_info->data_file_name = m_prebuilt->table->data_dir_path;
13935 }
13936
13937 /* Update the TABLESPACE name from the Data Dictionary. */
13938 101119 dict_get_and_save_space_name(m_prebuilt->table);
13939
13940 /* Put this tablespace name into the create_info structure so that
13941 SHOW CREATE TABLE will display TABLESPACE=name. This also affects
13942 an ALTER TABLE which must know the current TABLESPACE so that the
13943 table will stay there. */
13944
4/4
✓ Branch 0 taken 29461 times.
✓ Branch 1 taken 71658 times.
✓ Branch 2 taken 2316 times.
✓ Branch 3 taken 98803 times.
130580 if (m_prebuilt->table->tablespace != nullptr &&
13945
2/2
✓ Branch 0 taken 2316 times.
✓ Branch 1 taken 27145 times.
29461 create_info->tablespace == nullptr) {
13946 2316 create_info->tablespace = m_prebuilt->table->tablespace;
13947 }
13948 101119 }
13949
13950 /** Initialize the table FTS stopword list
13951 @return true if success */
13952 768 bool innobase_fts_load_stopword(
13953 dict_table_t *table, /*!< in: Table has the FTS */
13954 trx_t *trx, /*!< in: transaction */
13955 THD *thd) /*!< in: current thread */
13956 {
13957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
768 ut_ad(!dict_sys_mutex_own());
13958
13959 2304 return (fts_load_stopword(table, trx, innobase_server_stopword_table,
13960 768 THDVAR(thd, ft_user_stopword_table),
13961 1536 THDVAR(thd, ft_enable_stopword), false));
13962 }
13963
13964 12008 static bool innobase_ddse_dict_init(
13965 dict_init_mode_t dict_init_mode, uint, List<const dd::Object_table> *tables,
13966 List<const Plugin_tablespace> *tablespaces) {
13967
1/2
✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
12008 DBUG_TRACE;
13968
13969
8/16
✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12008 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12008 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12008 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12008 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 12008 times.
✗ Branch 15 not taken.
12008 LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_START_INITIALIZE);
13970
13971
2/4
✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12008 times.
✗ Branch 3 not taken.
12008 assert(tables && tables->is_empty());
13972
2/4
✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12008 times.
✗ Branch 3 not taken.
12008 assert(tablespaces && tablespaces->is_empty());
13973
13974
2/2
✓ Branch 0 taken 11934 times.
✓ Branch 1 taken 74 times.
12008 if (dblwr::is_enabled()) {
13975
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 11926 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
11934 if (innobase_doublewrite_dir != nullptr && *innobase_doublewrite_dir != 0) {
13976
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 dblwr::dir.assign(innobase_doublewrite_dir);
13977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 switch (dblwr::dir.front()) {
13978 case '#':
13979 case '.':
13980 break;
13981 8 default:
13982
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (!Fil_path::is_absolute_path(dblwr::dir)) {
13983 dblwr::dir.insert(0, "#");
13984 }
13985 }
13986
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
16 ib::info(ER_IB_MSG_DBLWR_1325)
13987
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
16 << "Using " << dblwr::dir << " as doublewrite directory";
13988 } else {
13989
1/2
✓ Branch 0 taken 11926 times.
✗ Branch 1 not taken.
11926 dblwr::dir.assign(".");
13990 }
13991
2/4
✓ Branch 0 taken 11934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11934 times.
✗ Branch 3 not taken.
11934 ib::info(ER_IB_MSG_DBLWR_1304) << "Atomic write enabled";
13992 } else {
13993
2/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
74 ib::info(ER_IB_MSG_DBLWR_1305) << "Atomic write disabled";
13994 }
13995
13996 12008 bool is_dd_encrypted{false};
13997
13998
3/4
✓ Branch 0 taken 12007 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 11920 times.
12008 if (innobase_init_files(dict_init_mode, tablespaces, is_dd_encrypted)) {
13999 87 return true;
14000 }
14001
14002 /* Instantiate table defs only if we are successful so far. */
14003 dd::Object_table *innodb_dynamic_metadata =
14004
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 dd::Object_table::create_object_table();
14005
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 innodb_dynamic_metadata->set_hidden(true);
14006 dd::Object_table_definition *def =
14007
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 innodb_dynamic_metadata->target_table_definition();
14008
2/4
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
11920 def->set_table_name("innodb_dynamic_metadata");
14009
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(0, "table_id", "table_id BIGINT UNSIGNED NOT NULL");
14010
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(1, "version", "version BIGINT UNSIGNED NOT NULL");
14011
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(2, "metadata", "metadata BLOB NOT NULL");
14012
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_index(0, "index_pk", "PRIMARY KEY (table_id)");
14013 /* Options and tablespace are set at the SQL layer. */
14014
14015 /* Changing these values would change the specification of innodb statistics
14016 tables. */
14017 static constexpr size_t DB_NAME_FIELD_SIZE = 64;
14018 static constexpr size_t TABLE_NAME_FIELD_SIZE = 199;
14019
14020 static_assert(DB_NAME_FIELD_SIZE == dict_name::MAX_DB_CHAR_LEN,
14021 "dict_name::MAX_DB_CHAR_LEN mismatch with db column");
14022
14023 static_assert(TABLE_NAME_FIELD_SIZE == dict_name::MAX_TABLE_CHAR_LEN,
14024 "dict_name::MAX_TABLE_CHAR_LEN mismatch with table column");
14025
14026 /* Set length for database name field. */
14027
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
23840 std::ostringstream db_name_field;
14028
2/4
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
11920 db_name_field << "database_name VARCHAR(" << DB_NAME_FIELD_SIZE
14029
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 << ") NOT NULL";
14030
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
23840 std::string db_field = db_name_field.str();
14031
14032 /* Set length for table name field. */
14033
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
23840 std::ostringstream table_name_field;
14034
2/4
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
11920 table_name_field << "table_name VARCHAR(" << TABLE_NAME_FIELD_SIZE
14035
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 << ") NOT NULL";
14036
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 std::string table_field = table_name_field.str();
14037
14038 dd::Object_table *innodb_table_stats =
14039
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 dd::Object_table::create_object_table();
14040
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 innodb_table_stats->set_hidden(false);
14041
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 def = innodb_table_stats->target_table_definition();
14042
2/4
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
11920 def->set_table_name("innodb_table_stats");
14043
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(0, "database_name", db_field.c_str());
14044
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(1, "table_name", table_field.c_str());
14045
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(2, "last_update",
14046 "last_update TIMESTAMP NOT NULL \n"
14047 " DEFAULT CURRENT_TIMESTAMP \n"
14048 " ON UPDATE CURRENT_TIMESTAMP");
14049
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(3, "n_rows", "n_rows BIGINT UNSIGNED NOT NULL");
14050
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(4, "clustered_index_size",
14051 "clustered_index_size BIGINT UNSIGNED NOT NULL");
14052
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(5, "sum_of_other_index_sizes",
14053 "sum_of_other_index_sizes BIGINT UNSIGNED NOT NULL");
14054
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_index(0, "index_pk", "PRIMARY KEY (database_name, table_name)");
14055 /* Options and tablespace are set at the SQL layer. */
14056
14057 dd::Object_table *innodb_index_stats =
14058
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 dd::Object_table::create_object_table();
14059
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 innodb_index_stats->set_hidden(false);
14060
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 def = innodb_index_stats->target_table_definition();
14061
2/4
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
11920 def->set_table_name("innodb_index_stats");
14062
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(0, "database_name", db_field.c_str());
14063
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(1, "table_name", table_field.c_str());
14064
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(2, "index_name", "index_name VARCHAR(64) NOT NULL");
14065
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(3, "last_update",
14066 "last_update TIMESTAMP NOT NULL"
14067 " DEFAULT CURRENT_TIMESTAMP"
14068 " ON UPDATE CURRENT_TIMESTAMP");
14069 /*
14070 There are at least: stat_name='size'
14071 stat_name='n_leaf_pages'
14072 stat_name='n_diff_pfx%'
14073 */
14074
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(4, "stat_name", "stat_name VARCHAR(64) NOT NULL");
14075
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(5, "stat_value", "stat_value BIGINT UNSIGNED NOT NULL");
14076
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(6, "sample_size", "sample_size BIGINT UNSIGNED");
14077
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(7, "stat_description",
14078 "stat_description VARCHAR(1024) NOT NULL");
14079
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_index(0, "index_pk",
14080 "PRIMARY KEY (database_name, table_name, "
14081 "index_name, stat_name)");
14082 /* Options and tablespace are set at the SQL layer. */
14083
14084
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 dd::Object_table *innodb_ddl_log = dd::Object_table::create_object_table();
14085
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 innodb_ddl_log->set_hidden(true);
14086
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 def = innodb_ddl_log->target_table_definition();
14087
2/4
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
11920 def->set_table_name("innodb_ddl_log");
14088
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(0, "id", "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT");
14089
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(1, "thread_id", "thread_id BIGINT UNSIGNED NOT NULL");
14090
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(2, "type", "type INT UNSIGNED NOT NULL");
14091
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(3, "space_id", "space_id INT UNSIGNED");
14092
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(4, "page_no", "page_no INT UNSIGNED");
14093
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(5, "index_id", "index_id BIGINT UNSIGNED");
14094
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(6, "table_id", "table_id BIGINT UNSIGNED");
14095
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(7, "old_file_path",
14096 "old_file_path VARCHAR(512) COLLATE UTF8_BIN");
14097
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_field(8, "new_file_path",
14098 "new_file_path VARCHAR(512) COLLATE UTF8_BIN");
14099
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_index(0, "index_pk", "PRIMARY KEY(id)");
14100
3/6
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
11920 def->add_index(1, "index_k_thread_id", "KEY(thread_id)");
14101 /* Options and tablespace are set at the SQL layer. */
14102
14103
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
11920 if (is_dd_encrypted) {
14104
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 innodb_dynamic_metadata->set_target_encrypted();
14105
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 innodb_table_stats->set_target_encrypted();
14106
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 innodb_index_stats->set_target_encrypted();
14107
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 innodb_ddl_log->set_target_encrypted();
14108 }
14109
14110
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 tables->push_back(innodb_dynamic_metadata);
14111
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 tables->push_back(innodb_table_stats);
14112
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 tables->push_back(innodb_index_stats);
14113
1/2
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
11920 tables->push_back(innodb_ddl_log);
14114
14115
8/16
✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11920 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11920 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11920 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11920 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11920 times.
✗ Branch 15 not taken.
11920 LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_END_INITIALIZE);
14116
14117 11920 return false;
14118 12007 }
14119
14120 /** Initialize the set of hard coded DD table ids.
14121 @param[in] dd_table_id Table id of DD table. */
14122 406345 static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id) {
14123 406345 dict_sys_t::s_dd_table_ids.insert(dd_table_id);
14124 406345 }
14125
14126 /** Parse the table name into normal name and remote path if needed.
14127 @param[in] name Table name (db/table or full path).
14128 @return 0 if successful, otherwise, error number */
14129 432840 int create_table_info_t::parse_table_name(const char *name) {
14130
1/2
✓ Branch 0 taken 432841 times.
✗ Branch 1 not taken.
432840 DBUG_TRACE;
14131
14132 #ifdef _WIN32
14133 /* Names passed in from server are in two formats:
14134 1. <database_name>/<table_name>: for normal table creation
14135 2. full path: for temp table creation, or DATA DIRECTORY.
14136
14137 When srv_file_per_table is on,
14138 check for full path pattern, i.e.
14139 X:\dir\..., X is a driver letter, or
14140 \\dir1\dir2\..., UNC path
14141 returns error if it is in full path format, but not creating a temp.
14142 table. Currently InnoDB does not support symbolic link on Windows. */
14143
14144 if (m_innodb_file_per_table &&
14145 !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
14146 if (name[1] == ':' || (name[0] == '\\' && name[1] == '\\')) {
14147 log_errlog(ERROR_LEVEL, ER_INNODB_CANNOT_CREATE_TABLE, name);
14148 return HA_ERR_GENERIC;
14149 }
14150 }
14151 #endif /* _WIN32 */
14152
14153
2/4
✓ Branch 0 taken 432841 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 432841 times.
432841 if (!normalize_table_name(m_table_name, name)) {
14154 /* purecov: begin inspected */
14155 ut_d(ut_error);
14156 ut_o(return (HA_ERR_TOO_LONG_PATH));
14157 /* purecov: end */
14158 }
14159
14160 432841 m_remote_path[0] = '\0';
14161 432841 m_tablespace[0] = '\0';
14162
14163 /* Set the remote path if DATA DIRECTORY is valid. If not,
14164 we ignore the DATA DIRECTORY. In strict mode, a non-valid
14165 value would have already been rejected. */
14166
2/2
✓ Branch 0 taken 19206 times.
✓ Branch 1 taken 413635 times.
432841 if (m_create_info->data_file_name != nullptr &&
14167
3/4
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 18731 times.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
19206 *m_create_info->data_file_name != '\0' && m_table_name != nullptr) {
14168
3/4
✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 462 times.
475 if (!create_option_data_directory_is_valid(true)) {
14169
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED,
14170 ER_DEFAULT(WARN_OPTION_IGNORED), "DATA DIRECTORY");
14171 13 m_flags &= ~DICT_TF_MASK_DATA_DIR;
14172 } else {
14173 462 strncpy(m_remote_path, m_create_info->data_file_name, FN_REFLEN - 1);
14174 }
14175 }
14176
14177
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 432803 times.
432841 if (m_create_info->index_file_name) {
14178
2/4
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
38 push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED,
14179 ER_DEFAULT(WARN_OPTION_IGNORED), "INDEX DIRECTORY");
14180 }
14181
14182 /* The TABLESPACE designation has already been validated by
14183 create_option_tablespace_is_valid() irregardless of strict-mode.
14184 So it only needs to be copied now. */
14185
2/2
✓ Branch 0 taken 30520 times.
✓ Branch 1 taken 402321 times.
432841 if (m_use_shared_space) {
14186 30520 strncpy(m_tablespace, m_create_info->tablespace, NAME_LEN - 1);
14187 }
14188
14189 432841 return 0;
14190 432841 }
14191
14192 /** Determine InnoDB table flags.
14193 If strict_mode=OFF, this will adjust the flags to what should be assumed.
14194 However, if an existing general tablespace is being targeted, we will NOT
14195 assume anything or adjust these flags.
14196 @retval true if successful, false if error */
14197 428403 bool create_table_info_t::innobase_table_flags() {
14198
1/2
✓ Branch 0 taken 428404 times.
✗ Branch 1 not taken.
428403 DBUG_TRACE;
14199
14200 428404 const char *fts_doc_id_index_bad = nullptr;
14201 428404 uint32_t zip_ssize = 0;
14202 428404 const bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
14203 428404 bool zip_allowed = !is_temp;
14204
14205 const uint32_t zip_ssize_max =
14206 428404 std::min<uint32_t>((UNIV_PAGE_SSIZE_MAX), (PAGE_ZIP_SSIZE_MAX));
14207
14208 428403 m_flags = 0;
14209 428403 m_flags2 = 0;
14210
14211 /* Validate the page compression parameter. */
14212
1/2
✓ Branch 0 taken 428404 times.
✗ Branch 1 not taken.
428403 if (!create_option_compression_is_valid()) {
14213 /* No need to do anything. Warnings were issued.
14214 The compresion setting will be ignored later.
14215 If inodb_strict_mode=ON, this is called twice unless
14216 there was a problem before.
14217 If inodb_strict_mode=OFF, this is the only call. */
14218 }
14219
14220 /* Validate the page encryption parameter. */
14221
2/2
✓ Branch 0 taken 75202 times.
✓ Branch 1 taken 353202 times.
428404 if (m_create_info->encrypt_type.length > 0) {
14222 75202 const char *encryption = m_create_info->encrypt_type.str;
14223
14224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75202 times.
75202 if (Encryption::validate(encryption) != DB_SUCCESS) {
14225 /* Incorrect encryption option */
14226 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
14227 return false;
14228 }
14229 }
14230
14231 /* Check if there are any FTS indexes defined on this table. */
14232
2/2
✓ Branch 0 taken 196570 times.
✓ Branch 1 taken 428401 times.
624971 for (uint i = 0; i < m_form->s->keys; i++) {
14233 196570 const KEY *key = &m_form->key_info[i];
14234
14235
2/2
✓ Branch 0 taken 2209 times.
✓ Branch 1 taken 194361 times.
196570 if (key->flags & HA_FULLTEXT) {
14236 2209 m_flags2 |= DICT_TF2_FTS;
14237
14238 /* We don't support FTS indexes in temporary
14239 tables. */
14240
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2208 times.
2209 if (is_temp) {
14241
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_INNODB_NO_FT_TEMP_TABLE, MYF(0));
14242 1 return false;
14243 }
14244
14245
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2206 times.
2208 if (fts_doc_id_index_bad) {
14246 2 goto index_bad;
14247 }
14248
2/2
✓ Branch 0 taken 1200 times.
✓ Branch 1 taken 193161 times.
194361 } else if (key->flags & HA_SPATIAL) {
14249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1200 times.
1200 assert(~m_create_info->options &
14250 (HA_LEX_CREATE_TMP_TABLE | HA_LEX_CREATE_INTERNAL_TMP_TABLE));
14251 }
14252
14253
3/4
✓ Branch 0 taken 196567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 196519 times.
✓ Branch 3 taken 48 times.
196567 if (innobase_strcasecmp(key->name, FTS_DOC_ID_INDEX_NAME)) {
14254 196519 continue;
14255 }
14256
14257 /* Do a pre-check on FTS DOC ID index */
14258
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (!(key->flags & HA_NOSAME)
14259 /* For now, we do not allow a descending index,
14260 because fts_doc_fetch_by_doc_id() uses the
14261 InnODB SQL interpreter to look up FTS_DOC_ID.*/
14262
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 5 times.
48 || (key->key_part[0].key_part_flag & HA_REVERSE_SORT) ||
14263
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 strcmp(key->name, FTS_DOC_ID_INDEX_NAME) ||
14264
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
43 strcmp(key->key_part[0].field->field_name, FTS_DOC_ID_COL_NAME)) {
14265 7 fts_doc_id_index_bad = key->name;
14266 }
14267
14268
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
48 if (fts_doc_id_index_bad && (m_flags2 & DICT_TF2_FTS)) {
14269 index_bad:
14270
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0), fts_doc_id_index_bad);
14271 2 return false;
14272 }
14273 }
14274
14275
4/4
✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199620 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 228765 times.
428401 if (is_temp && m_create_info->key_block_size > 0) {
14276
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
14277 "InnoDB: KEY_BLOCK_SIZE is ignored"
14278 " for TEMPORARY TABLE.");
14279 16 zip_allowed = false;
14280
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 427833 times.
428385 } else if (m_create_info->key_block_size > 0) {
14281
1/2
✓ Branch 0 taken 552 times.
✗ Branch 1 not taken.
552 zip_ssize = get_zip_shift_size(m_create_info->key_block_size);
14282
14283 /* Make sure compressed row format is allowed. */
14284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (is_temp) {
14285 push_warning(m_thd, Sql_condition::SL_WARNING,
14286 ER_ILLEGAL_HA_CREATE_OPTION,
14287 "InnoDB: KEY_BLOCK_SIZE is ignored"
14288 " for TEMPORARY TABLE.");
14289 zip_allowed = false;
14290
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 537 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
552 } else if (!m_allow_file_per_table && !m_use_shared_space) {
14291
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 push_warning(m_thd, Sql_condition::SL_WARNING,
14292 ER_ILLEGAL_HA_CREATE_OPTION,
14293 "InnoDB: KEY_BLOCK_SIZE requires"
14294 " innodb_file_per_table.");
14295 15 zip_allowed = false;
14296 }
14297
14298
5/6
✓ Branch 0 taken 537 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 532 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
552 if (!zip_allowed || (!zip_ssize && m_create_info->key_block_size)) {
14299 20 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14300 ER_ILLEGAL_HA_CREATE_OPTION,
14301 "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32 ".",
14302
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 m_create_info->key_block_size);
14303 }
14304 }
14305
14306 428401 enum row_type row_type = m_form->s->row_type;
14307
14308
4/4
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 427855 times.
✓ Branch 2 taken 532 times.
✓ Branch 3 taken 14 times.
428401 if (zip_ssize && zip_allowed) {
14309 /* if ROW_FORMAT is set to default,
14310 automatically change it to COMPRESSED. */
14311
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 354 times.
532 if (row_type == ROW_TYPE_DEFAULT) {
14312 178 row_type = ROW_TYPE_COMPRESSED;
14313
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 336 times.
354 } else if (row_type != ROW_TYPE_COMPRESSED) {
14314 /* ROW_FORMAT other than COMPRESSED
14315 ignores KEY_BLOCK_SIZE. It does not
14316 make sense to reject conflicting
14317 KEY_BLOCK_SIZE and ROW_FORMAT, because
14318 such combinations can be obtained
14319 with ALTER TABLE anyway. */
14320 18 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14321 ER_ILLEGAL_HA_CREATE_OPTION,
14322 "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32
14323 " as ROW_FORMAT is not COMPRESSED.",
14324
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 m_create_info->key_block_size);
14325 18 zip_allowed = false;
14326 }
14327 } else {
14328 /* zip_ssize == 0 means no KEY_BLOCK_SIZE. */
14329
4/4
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 427572 times.
✓ Branch 2 taken 277 times.
✓ Branch 3 taken 20 times.
427869 if (row_type == ROW_TYPE_COMPRESSED && zip_allowed) {
14330 /* ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE
14331 implies half the maximum KEY_BLOCK_SIZE(*1k) or
14332 UNIV_PAGE_SIZE, whichever is less. */
14333 277 zip_ssize = zip_ssize_max - 1;
14334 }
14335 }
14336
14337
1/2
✓ Branch 0 taken 428400 times.
✗ Branch 1 not taken.
428401 rec_format_t innodb_row_format = get_row_format(innodb_default_row_format);
14338
6/7
✓ Branch 0 taken 701 times.
✓ Branch 1 taken 815 times.
✓ Branch 2 taken 811 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 38066 times.
✓ Branch 5 taken 388002 times.
✗ Branch 6 not taken.
428400 switch (row_type) {
14339 701 case ROW_TYPE_REDUNDANT:
14340 701 innodb_row_format = REC_FORMAT_REDUNDANT;
14341 701 break;
14342 815 case ROW_TYPE_COMPACT:
14343 815 innodb_row_format = REC_FORMAT_COMPACT;
14344 815 break;
14345
14346 811 case ROW_TYPE_COMPRESSED:
14347
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 798 times.
811 if (is_temp) {
14348
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14349 ER_ILLEGAL_HA_CREATE_OPTION,
14350 "InnoDB: %s is ignored for TEMPORARY TABLE.",
14351 get_row_format_name(row_type));
14352
14353 /* DYNAMIC row format is closer to COMPRESSED
14354 in that it supports better for large BLOBs. */
14355
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 push_warning(m_thd, Sql_condition::SL_WARNING,
14356 ER_ILLEGAL_HA_CREATE_OPTION,
14357 "InnoDB: assuming ROW_FORMAT=DYNAMIC.");
14358
14359 13 row_type = ROW_TYPE_DYNAMIC;
14360 13 innodb_row_format = REC_FORMAT_DYNAMIC;
14361 13 break;
14362 }
14363
14364 /* ROW_FORMAT=COMPRESSED requires file_per_table unless
14365 there is a target tablespace. */
14366
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 790 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
798 if (!m_allow_file_per_table && !m_use_shared_space) {
14367
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14368 ER_ILLEGAL_HA_CREATE_OPTION,
14369 "InnoDB: %s requires innodb_file_per_table.",
14370 get_row_format_name(row_type));
14371 } else {
14372 /* We can use this row_format. */
14373 790 innodb_row_format = REC_FORMAT_COMPRESSED;
14374 790 break;
14375 }
14376 8 zip_allowed = false;
14377 /* fall through to set row_type = DYNAMIC */
14378 [[fallthrough]];
14379 13 case ROW_TYPE_NOT_USED:
14380 case ROW_TYPE_FIXED:
14381 case ROW_TYPE_PAGED:
14382
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 push_warning(m_thd, Sql_condition::SL_WARNING,
14383 ER_ILLEGAL_HA_CREATE_OPTION,
14384 "InnoDB: assuming ROW_FORMAT=DYNAMIC.");
14385 [[fallthrough]];
14386 38079 case ROW_TYPE_DYNAMIC:
14387 38079 innodb_row_format = REC_FORMAT_DYNAMIC;
14388 38079 break;
14389 388002 case ROW_TYPE_DEFAULT: {
14390 /* Consider the real_row_type if already set. */
14391
4/5
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 143 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 387816 times.
✓ Branch 4 taken 12 times.
388002 switch (m_form->s->real_row_type) {
14392 31 case ROW_TYPE_REDUNDANT:
14393 31 innodb_row_format = REC_FORMAT_REDUNDANT;
14394 31 break;
14395 143 case ROW_TYPE_COMPACT:
14396 143 innodb_row_format = REC_FORMAT_COMPACT;
14397 143 break;
14398 case ROW_TYPE_COMPRESSED:
14399 innodb_row_format = REC_FORMAT_COMPRESSED;
14400 break;
14401 387816 case ROW_TYPE_DYNAMIC:
14402 387816 innodb_row_format = REC_FORMAT_DYNAMIC;
14403 387816 break;
14404 12 default:
14405 12 break;
14406 }
14407 388002 break;
14408 }
14409 default:
14410 ut_d(ut_error);
14411 }
14412
14413 /* Don't support compressed table when page size > 16k. */
14414
6/6
✓ Branch 0 taken 199585 times.
✓ Branch 1 taken 228815 times.
✓ Branch 2 taken 790 times.
✓ Branch 3 taken 198795 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 778 times.
428400 if (zip_allowed && zip_ssize && UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) {
14415
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
14416 "InnoDB: Cannot create a COMPRESSED table"
14417 " when innodb_page_size > 16k."
14418 " Assuming ROW_FORMAT=DYNAMIC.");
14419 12 zip_allowed = false;
14420 }
14421
14422
4/6
✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199619 times.
✓ Branch 2 taken 228781 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 428400 times.
428400 ut_ad(!is_temp || !zip_allowed);
14423
4/6
✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199619 times.
✓ Branch 2 taken 228781 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 428400 times.
428400 ut_ad(!is_temp || row_type != ROW_TYPE_COMPRESSED);
14424
5/6
✓ Branch 0 taken 228780 times.
✓ Branch 1 taken 199620 times.
✓ Branch 2 taken 228780 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 428400 times.
428400 ut_ad(!is_temp || innodb_row_format != REC_FORMAT_COMPRESSED);
14425
14426 /* Set the table flags */
14427
2/2
✓ Branch 0 taken 228827 times.
✓ Branch 1 taken 199573 times.
428400 if (!zip_allowed) {
14428 228827 zip_ssize = 0;
14429 }
14430
14431
2/2
✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199619 times.
428400 if (is_temp) {
14432 228781 m_flags2 |= DICT_TF2_TEMPORARY;
14433
14434
2/2
✓ Branch 0 taken 182646 times.
✓ Branch 1 taken 46135 times.
228781 if (m_create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) {
14435 /* Intrinsic tables reside only in the shared temporary
14436 tablespace and we will always use ROW_FORMAT=DYNAMIC. */
14437 /* We do not allow compressed instrinsic temporary tables. */
14438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182646 times.
182646 ut_ad(zip_ssize == 0);
14439 182646 innodb_row_format = REC_FORMAT_DYNAMIC;
14440 182646 m_flags2 |= DICT_TF2_INTRINSIC;
14441 }
14442
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 228772 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
228781 if (m_use_shared_space && m_create_info->tablespace != nullptr &&
14443
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0) {
14444 /* This is possible only with innodb_strict_mode=OFF and we warned that
14445 that tablespace=innodb_temporary is ignored. We should instead use
14446 session temporary tablespaces */
14447 9 m_use_shared_space = false;
14448 }
14449
14450
2/2
✓ Branch 0 taken 150894 times.
✓ Branch 1 taken 48725 times.
199619 } else if (m_use_file_per_table) {
14451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 150894 times.
150894 ut_ad(!m_use_shared_space);
14452 150894 m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE;
14453 }
14454
14455 /* Set the table flags */
14456 428400 dict_tf_set(&m_flags, innodb_row_format, zip_ssize, m_use_data_dir,
14457
1/2
✓ Branch 0 taken 428400 times.
✗ Branch 1 not taken.
428400 m_use_shared_space);
14458
14459 428400 return true;
14460 428403 }
14461
14462 /** Detach the just created table and its auxiliary tables if exist */
14463 146491 void create_table_info_t::detach() {
14464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
146491 ut_ad(!dict_sys_mutex_own());
14465 146491 dict_sys_mutex_enter();
14466
14467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
146491 ut_ad(m_table != nullptr);
14468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
146491 ut_ad(!m_table->can_be_evicted);
14469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
146491 ut_ad(!m_table->is_temporary());
14470
14471
2/2
✓ Branch 0 taken 134757 times.
✓ Branch 1 taken 11734 times.
146491 if (!m_table->explicitly_non_lru) {
14472 134757 dict_table_allow_eviction(m_table);
14473 }
14474
14475
2/2
✓ Branch 0 taken 145948 times.
✓ Branch 1 taken 543 times.
146491 if ((m_table->flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) ||
14476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145948 times.
145948 m_table->fts != nullptr) {
14477 543 fts_detach_aux_tables(m_table, true);
14478 }
14479
14480 146491 dict_sys_mutex_exit();
14481 146491 }
14482
14483 /** Parse MERGE_THRESHOLD value from the string.
14484 @param[in] thd connection
14485 @param[in] str string which might include 'MERGE_THRESHOLD='
14486 @return value parsed. 0 means not found or invalid value. */
14487 33595 static ulint innobase_parse_merge_threshold(THD *thd, const char *str) {
14488 static const char *label = "MERGE_THRESHOLD=";
14489
3/4
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 33064 times.
✓ Branch 2 taken 531 times.
✗ Branch 3 not taken.
33595 static const size_t label_len = strlen(label);
14490 33595 const char *pos = str;
14491
14492 33595 pos = strstr(str, label);
14493
14494
2/2
✓ Branch 0 taken 33528 times.
✓ Branch 1 taken 67 times.
33595 if (pos == nullptr) {
14495 33528 return (0);
14496 }
14497
14498 67 pos += label_len;
14499
14500 67 lint ret = atoi(pos);
14501
14502
4/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 10 times.
67 if (ret > 0 && ret <= 50) {
14503 48 return (static_cast<ulint>(ret));
14504 }
14505
14506 19 push_warning_printf(
14507 thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION,
14508 "InnoDB: Invalid value for MERGE_THRESHOLD in the CREATE TABLE"
14509 " statement. The value is ignored.");
14510
14511 19 return (0);
14512 }
14513
14514 /** Parse hint for table and its indexes, and update the information
14515 in dictionary.
14516 @param[in] thd Connection thread
14517 @param[in,out] table Target table
14518 @param[in] table_share Table definition */
14519 473479 void innobase_parse_hint_from_comment(THD *thd, dict_table_t *table,
14520 const TABLE_SHARE *table_share) {
14521 ulint merge_threshold_table;
14522 ulint merge_threshold_index[MAX_KEY];
14523 bool is_found[MAX_KEY];
14524
14525
2/2
✓ Branch 0 taken 33391 times.
✓ Branch 1 taken 440088 times.
473479 if (table_share->comment.str != nullptr) {
14526 merge_threshold_table =
14527
1/2
✓ Branch 0 taken 33391 times.
✗ Branch 1 not taken.
33391 innobase_parse_merge_threshold(thd, table_share->comment.str);
14528 } else {
14529 440088 merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT;
14530 }
14531
14532
2/2
✓ Branch 0 taken 33381 times.
✓ Branch 1 taken 440098 times.
473479 if (merge_threshold_table == 0) {
14533 33381 merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT;
14534 }
14535
14536
2/2
✓ Branch 0 taken 238182 times.
✓ Branch 1 taken 473479 times.
711661 for (uint i = 0; i < table_share->keys; i++) {
14537 238182 KEY *key_info = &table_share->key_info[i];
14538
14539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238182 times.
238182 ut_ad(i < sizeof(merge_threshold_index) / sizeof(merge_threshold_index[0]));
14540
14541
3/4
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 237978 times.
✓ Branch 2 taken 204 times.
✗ Branch 3 not taken.
238182 if (key_info->flags & HA_USES_COMMENT && key_info->comment.str != nullptr) {
14542 204 merge_threshold_index[i] =
14543
1/2
✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
204 innobase_parse_merge_threshold(thd, key_info->comment.str);
14544 } else {
14545 237978 merge_threshold_index[i] = merge_threshold_table;
14546 }
14547
14548
2/2
✓ Branch 0 taken 166 times.
✓ Branch 1 taken 238016 times.
238182 if (merge_threshold_index[i] == 0) {
14549 166 merge_threshold_index[i] = merge_threshold_table;
14550 }
14551 }
14552
14553
2/2
✓ Branch 0 taken 238182 times.
✓ Branch 1 taken 473479 times.
711661 for (uint i = 0; i < table_share->keys; i++) {
14554 238182 is_found[i] = false;
14555 }
14556
14557 /* update in memory */
14558
6/10
✓ Branch 0 taken 473479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 473479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 565545 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1039024 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 565545 times.
✓ Branch 9 taken 473479 times.
1039024 for (auto index : table->indexes) {
14559
2/2
✓ Branch 0 taken 326224 times.
✓ Branch 1 taken 239321 times.
565545 if (dict_index_is_auto_gen_clust(index)) {
14560 /* GEN_CLUST_INDEX should use merge_threshold_table */
14561
14562 /* x-lock index is needed to exclude concurrent
14563 pessimistic tree operations */
14564
2/4
✓ Branch 0 taken 326224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326224 times.
✗ Branch 3 not taken.
326224 rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE);
14565 326224 index->merge_threshold = merge_threshold_table;
14566
2/4
✓ Branch 0 taken 326224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326224 times.
✗ Branch 3 not taken.
326224 rw_lock_x_unlock(dict_index_get_lock(index));
14567
14568 326224 continue;
14569 }
14570
14571
2/2
✓ Branch 0 taken 429162 times.
✓ Branch 1 taken 1146 times.
430308 for (uint i = 0; i < table_share->keys; i++) {
14572
2/2
✓ Branch 0 taken 188841 times.
✓ Branch 1 taken 240321 times.
429162 if (is_found[i]) {
14573 188841 continue;
14574 }
14575
14576 240321 KEY *key_info = &table_share->key_info[i];
14577
14578
3/4
✓ Branch 0 taken 240321 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238175 times.
✓ Branch 3 taken 2146 times.
240321 if (innobase_strcasecmp(index->name, key_info->name) == 0) {
14579 /* x-lock index is needed to exclude concurrent
14580 pessimistic tree operations */
14581
2/4
✓ Branch 0 taken 238175 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238175 times.
✗ Branch 3 not taken.
238175 rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE);
14582 238175 index->merge_threshold = merge_threshold_index[i];
14583
2/4
✓ Branch 0 taken 238175 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238175 times.
✗ Branch 3 not taken.
238175 rw_lock_x_unlock(dict_index_get_lock(index));
14584 238175 is_found[i] = true;
14585
14586 238175 break;
14587 }
14588 }
14589 }
14590 473479 }
14591
14592 /** Set m_use_* flags. */
14593 481074 void create_table_info_t::set_tablespace_type(
14594 bool table_being_altered_is_file_per_table) {
14595 /* Note whether this table will be created using a shared,
14596 general or system tablespace. */
14597 481074 m_use_shared_space = tablespace_is_shared_space(m_create_info);
14598
14599 /** Allow file_per_table for this table either because:
14600 1) the setting innodb_file_per_table=on,
14601 2) the table being altered is currently file_per_table
14602 3) explicitly requested by tablespace=innodb_file_per_table. */
14603
1/2
✓ Branch 0 taken 21479 times.
✗ Branch 1 not taken.
21479 m_allow_file_per_table = m_innodb_file_per_table ||
14604
4/4
✓ Branch 0 taken 21479 times.
✓ Branch 1 taken 459596 times.
✓ Branch 2 taken 147 times.
✓ Branch 3 taken 21332 times.
502554 table_being_altered_is_file_per_table ||
14605 21479 tablespace_is_file_per_table(m_create_info);
14606
14607 481075 bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
14608
14609 /* Ignore the current innodb_file_per_table setting if we are
14610 creating a temporary table or if the
14611 TABLESPACE= phrase is using an existing shared tablespace. */
14612 481075 m_use_file_per_table =
14613
6/6
✓ Branch 0 taken 459743 times.
✓ Branch 1 taken 21332 times.
✓ Branch 2 taken 231120 times.
✓ Branch 3 taken 228623 times.
✓ Branch 4 taken 200312 times.
✓ Branch 5 taken 30808 times.
481075 m_allow_file_per_table && !is_temp && !m_use_shared_space;
14614
14615 /* DATA DIRECTORY must have m_use_file_per_table. */
14616 1162462 m_use_data_dir = m_use_file_per_table &&
14617
4/4
✓ Branch 0 taken 200312 times.
✓ Branch 1 taken 280763 times.
✓ Branch 2 taken 16299 times.
✓ Branch 3 taken 184013 times.
497374 (m_create_info->data_file_name != nullptr) &&
14618
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 15651 times.
16299 (m_create_info->data_file_name[0] != '\0');
14619
4/6
✓ Branch 0 taken 47332 times.
✓ Branch 1 taken 433743 times.
✓ Branch 2 taken 47332 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 481075 times.
481075 ut_ad(!(m_use_shared_space && m_use_data_dir));
14620 481075 }
14621
14622 /** Initialize the create_table_info_t object.
14623 @return error number */
14624 410863 int create_table_info_t::initialize() {
14625
1/2
✓ Branch 0 taken 410864 times.
✗ Branch 1 not taken.
410863 DBUG_TRACE;
14626
14627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 410864 times.
410864 ut_ad(m_thd != nullptr);
14628
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 410863 times.
410864 ut_ad(m_create_info != nullptr);
14629
14630
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 410853 times.
410863 if (m_form->s->fields > REC_MAX_N_USER_FIELDS) {
14631 10 return HA_ERR_TOO_MANY_FIELDS;
14632 }
14633
14634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 410853 times.
410853 ut_ad(m_form->s->row_type == m_create_info->row_type);
14635
14636 /* Check for name conflicts (with reserved name) for
14637 any user indices to be created. */
14638
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 410851 times.
410853 if (innobase_index_name_is_reserved(m_thd, m_form->key_info,
14639
1/2
✓ Branch 0 taken 410853 times.
✗ Branch 1 not taken.
410853 m_form->s->keys)) {
14640 2 return HA_ERR_WRONG_INDEX;
14641 }
14642
14643 410851 m_trx->will_lock++;
14644
14645 410851 m_table = nullptr;
14646
14647 410851 return 0;
14648 410863 }
14649
14650 /** Initialize the autoinc of this table if necessary, which should
14651 be called before we flush logs, so autoinc counter can be persisted. */
14652 429022 void create_table_info_t::initialize_autoinc() {
14653 dict_table_t *innobase_table;
14654
14655
2/2
✓ Branch 0 taken 200216 times.
✓ Branch 1 taken 228806 times.
629238 const bool persist = !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
14656
2/2
✓ Branch 0 taken 17539 times.
✓ Branch 1 taken 182677 times.
200216 m_form->found_next_number_field;
14657
14658
4/4
✓ Branch 0 taken 411483 times.
✓ Branch 1 taken 17539 times.
✓ Branch 2 taken 410627 times.
✓ Branch 3 taken 856 times.
429022 if (!persist && m_create_info->auto_increment_value == 0) {
14659 410627 return;
14660 }
14661
14662 innobase_table =
14663 18395 thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name);
14664
14665
1/2
✓ Branch 0 taken 18395 times.
✗ Branch 1 not taken.
18395 if (innobase_table == nullptr) {
14666 18395 innobase_table = dd_table_open_on_name_in_mem(m_table_name, false);
14667 } else {
14668 innobase_table->acquire();
14669 ut_ad(innobase_table->is_intrinsic());
14670 }
14671
14672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18395 times.
18395 assert(innobase_table != nullptr);
14673
14674
2/2
✓ Branch 0 taken 17539 times.
✓ Branch 1 taken 856 times.
18395 if (persist) {
14675 17539 dict_table_autoinc_set_col_pos(
14676 17539 innobase_table, m_form->found_next_number_field->field_index());
14677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17539 times.
17539 ut_ad(dict_table_has_autoinc_col(innobase_table));
14678 }
14679
14680 /* We need to copy the AUTOINC value from the old table if
14681 this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX
14682 does a table copy too. If query was one of :
14683
14684 CREATE TABLE ...AUTO_INCREMENT = x; or
14685 ALTER TABLE...AUTO_INCREMENT = x; or
14686 OPTIMIZE TABLE t; or
14687 CREATE INDEX x on t(...);
14688
14689 Find out a table definition from the dictionary and get
14690 the current value of the auto increment field. Set a new
14691 value to the auto increment field if the value is greater
14692 than the maximum value in the column. */
14693
14694 18395 enum_sql_command cmd = static_cast<enum_sql_command>(thd_sql_command(m_thd));
14695
14696
2/2
✓ Branch 0 taken 2107 times.
✓ Branch 1 taken 16288 times.
18395 if (m_create_info->auto_increment_value > 0 &&
14697
4/4
✓ Branch 0 taken 1766 times.
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 1724 times.
2107 ((m_create_info->used_fields & HA_CREATE_USED_AUTO) ||
14698
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 19 times.
42 cmd == SQLCOM_ALTER_TABLE || cmd == SQLCOM_OPTIMIZE ||
14699 cmd == SQLCOM_CREATE_INDEX)) {
14700 uint64_t auto_inc_value;
14701
14702 2088 auto_inc_value = m_create_info->auto_increment_value;
14703
14704 2088 dict_table_autoinc_lock(innobase_table);
14705 2088 dict_table_autoinc_initialize(innobase_table, auto_inc_value);
14706 2088 dict_table_autoinc_unlock(innobase_table);
14707 }
14708
14709 18395 dd_table_close(innobase_table, nullptr, nullptr, false);
14710 }
14711
14712 /** Prepare to create a new table to an InnoDB database.
14713 @param[in] name Table name
14714 @return error number */
14715 433184 int create_table_info_t::prepare_create_table(const char *name) {
14716
1/2
✓ Branch 0 taken 433185 times.
✗ Branch 1 not taken.
433184 DBUG_TRACE;
14717
14718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 433185 times.
433185 ut_ad(m_thd != nullptr);
14719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 433185 times.
433185 ut_ad(m_form->s->row_type == m_create_info->row_type);
14720
14721
2/4
✓ Branch 0 taken 433184 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 433184 times.
433185 if (!normalize_table_name(m_table_name, name)) {
14722 /* purecov: begin inspected */
14723 ut_d(ut_error);
14724 ut_o(return (HA_ERR_TOO_LONG_PATH));
14725 /* purecov: end */
14726 }
14727
14728
1/2
✓ Branch 0 taken 433185 times.
✗ Branch 1 not taken.
433184 set_tablespace_type(false);
14729
14730 /* Validate the create options if innodb_strict_mode is set.
14731 Do not use the regular message for ER_ILLEGAL_HA_CREATE_OPTION
14732 because InnoDB might actually support the option, but not under
14733 the current conditions. The messages revealing the specific
14734 problems are reported inside this function. */
14735
3/4
✓ Branch 0 taken 433185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 343 times.
✓ Branch 3 taken 432842 times.
433185 if (create_options_are_invalid()) {
14736 343 return HA_WRONG_CREATE_OPTION;
14737 }
14738
14739 /* Create the table flags and flags2 */
14740
6/6
✓ Branch 0 taken 380704 times.
✓ Branch 1 taken 52138 times.
✓ Branch 2 taken 380691 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 380691 times.
✓ Branch 5 taken 52151 times.
432842 if (flags() == 0 && flags2() == 0) {
14741
3/4
✓ Branch 0 taken 380691 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 380690 times.
380691 if (!innobase_table_flags()) {
14742 1 return HA_WRONG_CREATE_OPTION;
14743 }
14744 }
14745
14746
5/8
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 432757 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 432841 times.
432841 ut_ad(!high_level_read_only || is_intrinsic_temp_table());
14747
14748
1/2
✓ Branch 0 taken 432840 times.
✗ Branch 1 not taken.
432841 return parse_table_name(name);
14749 433184 }
14750
14751 /** Check a column (name) is a base column for any stored column in the table
14752 @param[in] table TABLE* for the table
14753 @param[in] name column name to check
14754 @return true if this is a base column */
14755 267 static bool innobase_is_base_s_col(const TABLE *table, const char *name) {
14756
2/2
✓ Branch 0 taken 628 times.
✓ Branch 1 taken 257 times.
885 for (uint i = 0; i < table->s->fields; ++i) {
14757 628 const Field *field = table->field[i];
14758
14759
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 12 times.
628 if (!innobase_is_s_fld(field)) {
14760 616 continue;
14761 }
14762
14763
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 2 times.
19 for (uint j = 0; j < table->s->fields; ++j) {
14764
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 5 times.
17 if (bitmap_is_set(&field->gcol_info->base_columns_map, j)) {
14765 12 const Field *base_field = table->field[j];
14766
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if (innobase_strcasecmp(base_field->field_name, name) == 0) {
14767 10 return (true);
14768 }
14769 }
14770 }
14771 }
14772
14773 257 return (false);
14774 }
14775
14776 /** Check any cascading foreign key columns are base columns
14777 for any stored columns in the table
14778 @param[in] dd_table dd::Table for the table
14779 @param[in] table TABLE* for the table
14780 @return DB_NO_FK_ON_S_BASE_COL if found or DB_SUCCESS */
14781 246837 static dberr_t innobase_check_fk_base_col(const dd::Table *dd_table,
14782 const TABLE *table) {
14783
6/10
✓ Branch 0 taken 246837 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246838 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246838 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22646 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 22646 times.
✓ Branch 9 taken 246828 times.
269473 for (const dd::Foreign_key *key : dd_table->foreign_keys()) {
14784 22646 bool upd_cascade = false;
14785 22646 bool del_cascade = false;
14786
14787
3/5
✓ Branch 0 taken 22646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 22486 times.
✗ Branch 4 not taken.
22646 switch (key->update_rule()) {
14788 160 case dd::Foreign_key::RULE_CASCADE:
14789 case dd::Foreign_key::RULE_SET_NULL:
14790 160 upd_cascade = true;
14791 160 break;
14792 22486 case dd::Foreign_key::RULE_NO_ACTION:
14793 case dd::Foreign_key::RULE_RESTRICT:
14794 case dd::Foreign_key::RULE_SET_DEFAULT:
14795 22486 break;
14796 }
14797
14798
3/5
✓ Branch 0 taken 22646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✓ Branch 3 taken 22528 times.
✗ Branch 4 not taken.
22646 switch (key->delete_rule()) {
14799 118 case dd::Foreign_key::RULE_CASCADE:
14800 case dd::Foreign_key::RULE_SET_NULL:
14801 118 del_cascade = true;
14802 118 break;
14803 22528 case dd::Foreign_key::RULE_NO_ACTION:
14804 case dd::Foreign_key::RULE_RESTRICT:
14805 case dd::Foreign_key::RULE_SET_DEFAULT:
14806 22528 break;
14807 }
14808
14809
4/4
✓ Branch 0 taken 22486 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 22389 times.
✓ Branch 3 taken 97 times.
22646 if (!upd_cascade && !del_cascade) {
14810 22389 continue;
14811 }
14812
14813
6/10
✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 257 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 267 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 267 times.
✓ Branch 9 taken 247 times.
514 for (const dd::Foreign_key_element *key_e : key->elements()) {
14814
3/6
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 267 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 267 times.
✗ Branch 5 not taken.
267 dd::String_type col_name = key_e->column().name();
14815
14816
3/4
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 257 times.
267 if (innobase_is_base_s_col(table, col_name.c_str())) {
14817 10 return (DB_NO_FK_ON_S_BASE_COL);
14818 }
14819
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 10 times.
267 }
14820 }
14821 246828 return (DB_SUCCESS);
14822 }
14823
14824 /** Create the internal innodb table.
14825 @param[in] dd_table dd::Table or nullptr for intrinsic table
14826 @param[in] old_part_table dd::Table from an old partition for partitioned
14827 table, NULL otherwise.
14828 @return 0 or error number */
14829 429483 int create_table_info_t::create_table(const dd::Table *dd_table,
14830 const dd::Table *old_part_table) {
14831 int error;
14832 uint primary_key_no;
14833 uint i;
14834 const char *stmt;
14835 size_t stmt_len;
14836
14837
1/2
✓ Branch 0 taken 429484 times.
✗ Branch 1 not taken.
429483 DBUG_TRACE;
14838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429484 times.
429484 assert(m_form->s->keys <= MAX_KEY);
14839
14840 /* Check if dd table has hidden fts doc id index.
14841 Note: in case of TRUNCATE a fulltext table with
14842 hidden doc id index. */
14843
2/2
✓ Branch 0 taken 246838 times.
✓ Branch 1 taken 182646 times.
429484 if (dd_table != nullptr) {
14844
1/2
✓ Branch 0 taken 246838 times.
✗ Branch 1 not taken.
246838 dberr_t err = innobase_check_fk_base_col(dd_table, m_form);
14845
14846
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 246828 times.
246838 if (err != DB_SUCCESS) {
14847
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 error = convert_error_code_to_mysql(err, m_flags, nullptr);
14848
14849 10 return error;
14850 }
14851
14852
6/10
✓ Branch 0 taken 246828 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246828 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246828 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 318273 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 318273 times.
✓ Branch 9 taken 246828 times.
565101 for (auto index : dd_table->indexes()) {
14853
2/4
✓ Branch 0 taken 318273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318273 times.
✗ Branch 3 not taken.
318273 if (my_strcasecmp(system_charset_info, index->name().c_str(),
14854
4/4
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 317680 times.
✓ Branch 2 taken 586 times.
✓ Branch 3 taken 317687 times.
318866 FTS_DOC_ID_INDEX_NAME) == 0 &&
14855
3/4
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 586 times.
✓ Branch 3 taken 7 times.
593 index->is_hidden()) {
14856 586 m_flags2 |= DICT_TF2_FTS_ADD_DOC_ID;
14857 }
14858 }
14859 }
14860
14861 /* Look for a primary key */
14862 429474 primary_key_no = m_form->s->primary_key;
14863
14864 /* Our function innobase_get_mysql_key_number_for_index assumes
14865 the primary key is always number 0, if it exists */
14866
4/6
✓ Branch 0 taken 118927 times.
✓ Branch 1 taken 310547 times.
✓ Branch 2 taken 118927 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 429474 times.
429474 ut_a(primary_key_no == MAX_KEY || primary_key_no == 0);
14867
14868
1/2
✓ Branch 0 taken 429406 times.
✗ Branch 1 not taken.
429474 error = create_table_def(dd_table, old_part_table);
14869
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 429171 times.
429406 if (error) {
14870 235 return error;
14871 }
14872
14873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429171 times.
429171 ut_ad(m_table != nullptr);
14874
14875 /* Create the keys */
14876
14877
4/4
✓ Branch 0 taken 128525 times.
✓ Branch 1 taken 300646 times.
✓ Branch 2 taken 9741 times.
✓ Branch 3 taken 118784 times.
429171 if (m_form->s->keys == 0 || primary_key_no == MAX_KEY) {
14878 /* Create an index which is used as the clustered index;
14879 order the rows by their row id which is internally generated
14880 by InnoDB */
14881
14882 error =
14883
1/2
✓ Branch 0 taken 310387 times.
✗ Branch 1 not taken.
310387 create_clustered_index_when_no_primary(m_trx, m_flags, m_table_name);
14884
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 310362 times.
310387 if (error) {
14885 25 return error;
14886 }
14887 }
14888
14889
2/2
✓ Branch 0 taken 118784 times.
✓ Branch 1 taken 310362 times.
429146 if (primary_key_no != MAX_KEY) {
14890 /* In InnoDB the clustered index must always be created
14891 first */
14892
1/2
✓ Branch 0 taken 118733 times.
✗ Branch 1 not taken.
118784 error = create_index(m_trx, m_form, m_flags, m_table_name, primary_key_no,
14893 dd_table);
14894
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 118721 times.
118733 if (error) {
14895 12 return error;
14896 }
14897 }
14898
14899 /* Create the ancillary tables that are common to all FTS indexes on
14900 this table. */
14901
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428490 times.
429083 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) {
14902 fts_doc_id_index_enum ret;
14903
14904 /* Check whether there already exists FTS_DOC_ID_INDEX */
14905 1186 ret = innobase_fts_check_doc_id_index_in_def(m_form->s->keys,
14906
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 m_form->key_info);
14907
14908
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
✗ Branch 2 not taken.
593 switch (ret) {
14909 case FTS_INCORRECT_DOC_ID_INDEX:
14910 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14911 ER_WRONG_NAME_FOR_INDEX,
14912 " InnoDB: Index name %s is reserved"
14913 " for the unique index on"
14914 " FTS_DOC_ID column for FTS"
14915 " Document ID indexing"
14916 " on table %s. Please check"
14917 " the index definition to"
14918 " make sure it is of correct"
14919 " type\n",
14920 FTS_DOC_ID_INDEX_NAME, m_table->name.m_name);
14921
14922 if (m_table->fts) {
14923 fts_free(m_table);
14924 }
14925
14926 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), FTS_DOC_ID_INDEX_NAME);
14927 error = -1;
14928 return error;
14929 593 case FTS_EXIST_DOC_ID_INDEX:
14930 case FTS_NOT_EXIST_DOC_ID_INDEX:
14931 593 break;
14932 }
14933
14934
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 dberr_t err = fts_create_common_tables(m_trx, m_table, m_table_name,
14935 (ret == FTS_EXIST_DOC_ID_INDEX));
14936
14937
1/2
✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
593 error = convert_error_code_to_mysql(err, 0, nullptr);
14938
14939 593 DICT_TF2_FLAG_UNSET(m_table, DICT_TF2_FTS_ADD_DOC_ID);
14940
14941
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 589 times.
593 if (error) {
14942 4 return error;
14943 }
14944 }
14945
14946
2/2
✓ Branch 0 taken 191638 times.
✓ Branch 1 taken 429022 times.
620660 for (i = 0; i < m_form->s->keys; i++) {
14947
2/2
✓ Branch 0 taken 72919 times.
✓ Branch 1 taken 118719 times.
191638 if (i != primary_key_no) {
14948
1/2
✓ Branch 0 taken 72869 times.
✗ Branch 1 not taken.
72919 error = create_index(m_trx, m_form, m_flags, m_table_name, i, dd_table);
14949
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 72862 times.
72869 if (error) {
14950 7 return error;
14951 }
14952 }
14953 }
14954
14955
1/2
✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
429022 initialize_autoinc();
14956
14957 /* Cache all the FTS indexes on this table in the FTS specific
14958 structure. They are used for FTS indexed column update handling. */
14959
2/2
✓ Branch 0 taken 580 times.
✓ Branch 1 taken 428442 times.
429022 if (m_flags2 & DICT_TF2_FTS) {
14960 580 fts_t *fts = m_table->fts;
14961
14962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 580 times.
580 ut_a(fts != nullptr);
14963
14964
1/2
✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
580 dict_table_get_all_fts_indexes(m_table, fts->indexes);
14965 }
14966
14967
1/2
✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
429022 stmt = innobase_get_stmt_unsafe(m_thd, &stmt_len);
14968
14969
1/2
✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
429022 innodb_session_t *&priv = thd_to_innodb_session(m_trx->mysql_thd);
14970
1/2
✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
429022 dict_table_t *handler = priv->lookup_table_handler(m_table_name);
14971
14972
5/8
✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 246379 times.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 182643 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 429022 times.
429022 ut_ad(handler == nullptr || handler->is_intrinsic());
14973
5/8
✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 246379 times.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 182643 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 429022 times.
429022 ut_ad(handler == nullptr || is_intrinsic_temp_table());
14974
14975 /* There is no concept of foreign key for intrinsic tables. */
14976
4/6
✓ Branch 0 taken 246379 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 246379 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246379 times.
✗ Branch 5 not taken.
429022 if (handler == nullptr && stmt != nullptr && dd_table != nullptr
14977 /* FIXME: NewDD: WL#6049 should add a new call to check if a table
14978 is a parent table of any FK. If the table is not child table, nor
14979 parent table, then it can skip the check:
14980 dd_table->foreign_keys().empty() &&
14981 dd_table->referenced_keys().empty() */
14982 ) {
14983 246379 dberr_t err = DB_SUCCESS;
14984
14985
1/2
✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
246379 dict_sys_mutex_enter();
14986
1/2
✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
246379 err = row_table_load_foreign_constraints(m_trx, m_table_name, dd_table);
14987
1/2
✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
246379 dict_sys_mutex_exit();
14988
14989
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 246379 times.
246379 switch (err) {
14990 case DB_PARENT_NO_INDEX:
14991 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
14992 HA_ERR_CANNOT_ADD_FOREIGN,
14993 "Create table '%s' with foreign key constraint"
14994 " failed. There is no index in the referenced"
14995 " table where the referenced columns appear"
14996 " as the first columns.\n",
14997 m_table_name);
14998 break;
14999
15000 case DB_CHILD_NO_INDEX:
15001 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15002 HA_ERR_CANNOT_ADD_FOREIGN,
15003 "Create table '%s' with foreign key constraint"
15004 " failed. There is no index in the referencing"
15005 " table where referencing columns appear"
15006 " as the first columns.\n",
15007 m_table_name);
15008 break;
15009 case DB_NO_FK_ON_S_BASE_COL:
15010 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15011 HA_ERR_CANNOT_ADD_FOREIGN,
15012 "Create table '%s' with foreign key constraint"
15013 " failed. Cannot add foreign key constraint"
15014 " placed on the base column of stored"
15015 " column.\n",
15016 m_table_name);
15017 break;
15018 246379 default:
15019 246379 break;
15020 }
15021
15022
1/2
✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
246379 error = convert_error_code_to_mysql(err, m_flags, nullptr);
15023
15024
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 246378 times.
246379 if (error) {
15025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (handler != nullptr) {
15026 priv->unregister_table_handler(m_table_name);
15027 }
15028 1 return error;
15029 }
15030 }
15031
15032 429021 return 0;
15033 429315 }
15034
15035 /** Update a new table in an InnoDB database.
15036 @return error number */
15037 429018 int create_table_info_t::create_table_update_dict() {
15038
1/2
✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
429018 DBUG_TRACE;
15039
15040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429021 times.
429021 assert(m_table != nullptr);
15041
15042 #ifdef UNIV_DEBUG
15043
3/4
✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182643 times.
✓ Branch 3 taken 246378 times.
429021 if (m_table->is_intrinsic()) {
15044 dict_table_t *innobase_table =
15045
2/4
✓ Branch 0 taken 182643 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
182643 thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name);
15046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182643 times.
182643 ut_ad(m_table == innobase_table);
15047 }
15048 #endif /* UNIV_DEBUG */
15049
15050 /* Temp table must be uncompressed and reside in tmp tablespace. */
15051
2/4
✓ Branch 0 taken 429018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 429018 times.
429021 ut_ad(!dict_table_is_compressed_temporary(m_table));
15052
2/2
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 428433 times.
429018 if (m_table->fts != nullptr) {
15053
1/2
✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
585 if (m_table->fts_doc_id_index == nullptr) {
15054 1170 m_table->fts_doc_id_index =
15055
1/2
✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
585 dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME);
15056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
585 assert(m_table->fts_doc_id_index != nullptr);
15057 } else {
15058 assert(m_table->fts_doc_id_index ==
15059 dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME));
15060 }
15061 }
15062
15063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429018 times.
429018 assert((m_table->fts == nullptr) == (m_table->fts_doc_id_index == nullptr));
15064
15065
1/2
✓ Branch 0 taken 429017 times.
✗ Branch 1 not taken.
429018 innobase_copy_frm_flags_from_create_info(m_table, m_create_info);
15066
15067
1/2
✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
429017 dict_stats_update(m_table, DICT_STATS_EMPTY_TABLE);
15068
15069 /* Since no dict_table_close(), deinitialize it explicitly. */
15070
1/2
✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
429021 dict_stats_deinit(m_table);
15071
15072 /* Load server stopword into FTS cache */
15073
2/2
✓ Branch 0 taken 580 times.
✓ Branch 1 taken 428441 times.
429021 if (m_flags2 & DICT_TF2_FTS) {
15074
2/4
✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 580 times.
580 if (!innobase_fts_load_stopword(m_table, nullptr, m_thd)) {
15075 return -1;
15076 }
15077 }
15078
15079
1/2
✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
429021 innobase_parse_hint_from_comment(m_thd, m_table, m_form->s);
15080 429021 return 0;
15081 429021 }
15082
15083 /** Update the global data dictionary.
15084 @param[in] dd_table dd::Table or dd::Partition
15085 @retval 0 On success
15086 @retval error number On failure */
15087 template <typename Table>
15088 858042 int create_table_info_t::create_table_update_global_dd(Table *dd_table) {
15089
1/2
✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
858042 DBUG_TRACE;
15090
15091
4/4
✓ Branch 0 taken 246378 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 46162 times.
✓ Branch 3 taken 200216 times.
858042 if (dd_table == nullptr || (m_flags2 & DICT_TF2_TEMPORARY)) {
15092 /* No need to fill in metadata for all temporary tables.
15093 The Table object for temporary table is either NULL or
15094 a fake one, whose metadata would not be written back later */
15095 457610 return 0;
15096 }
15097
15098
2/2
✓ Branch 0 taken 17539 times.
✓ Branch 1 taken 182677 times.
400432 if (m_form->found_next_number_field != nullptr) {
15099
1/2
✓ Branch 0 taken 17539 times.
✗ Branch 1 not taken.
35078 dd_set_autoinc(dd_table->se_private_data(),
15100
1/2
✓ Branch 0 taken 17539 times.
✗ Branch 1 not taken.
35078 m_create_info->auto_increment_value);
15101 }
15102
15103
1/2
✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
400432 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
15104
1/2
✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
400432 dd::cache::Dictionary_client::Auto_releaser releaser(client);
15105
15106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200216 times.
400432 ut_ad(m_table != nullptr);
15107
2/4
✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 200216 times.
400432 ut_ad(!m_table->is_temporary());
15108
15109
1/2
✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
400432 bool file_per_table = dict_table_is_file_per_table(m_table);
15110 400432 dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID;
15111 400432 bool is_dd_table = m_table->space == dict_sys_t::s_dict_space_id;
15112
15113
2/2
✓ Branch 0 taken 29109 times.
✓ Branch 1 taken 171107 times.
400432 if (is_dd_table) {
15114 58218 dd_space_id = dict_sys_t::s_dd_dict_space_id;
15115
2/2
✓ Branch 0 taken 4727 times.
✓ Branch 1 taken 166380 times.
342214 } else if (m_table->space == TRX_SYS_SPACE) {
15116 9454 dd_space_id = dict_sys_t::s_dd_sys_space_id;
15117
2/2
✓ Branch 0 taken 165219 times.
✓ Branch 1 taken 1161 times.
332760 } else if (file_per_table) {
15118
1/2
✓ Branch 0 taken 165219 times.
✗ Branch 1 not taken.
330438 char *filename = fil_space_get_first_path(m_table->space);
15119
15120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165217 times.
330434 if (dd_create_implicit_tablespace(client, m_table->space,
15121
1/2
✓ Branch 0 taken 165217 times.
✗ Branch 1 not taken.
330438 m_table->name.m_name, filename, false,
15122 dd_space_id)) {
15123 ut::free(filename);
15124 return HA_ERR_GENERIC;
15125 }
15126
15127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165218 times.
330434 ut_ad(dd_space_id != dd::INVALID_OBJECT_ID);
15128 330436 ut::free(filename);
15129 } else {
15130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
2322 ut_ad(DICT_TF_HAS_SHARED_SPACE(m_table->flags));
15131
15132
1/2
✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
2322 dd_space_id = dd_get_space_id(*dd_table);
15133
15134 2322 const dd::Tablespace *index_space = nullptr;
15135
2/4
✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1161 times.
2322 if (client->acquire<dd::Tablespace>(dd_space_id, &index_space)) {
15136 return HA_ERR_GENERIC;
15137 }
15138
15139
2/4
✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1161 times.
2322 DBUG_EXECUTE_IF("create_table_update_dd_fail", index_space = nullptr;);
15140
15141 uint32_t id;
15142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
2322 if (index_space == nullptr) {
15143 my_error(ER_TABLESPACE_MISSING, MYF(0), m_table->name.m_name);
15144 return HA_ERR_TABLESPACE_MISSING;
15145
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2322 } else if (index_space->se_private_data().get(
15146
5/10
✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1161 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1161 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1161 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1161 times.
✗ Branch 9 not taken.
4644 dd_space_key_strings[DD_SPACE_ID], &id) ||
15147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
2322 id != m_table->space) {
15148 ut_ad(!"missing or incorrect tablespace id");
15149 return HA_ERR_GENERIC;
15150 }
15151 }
15152
15153 400432 m_table->dd_space_id = dd_space_id;
15154
15155
1/2
✓ Branch 0 taken 200215 times.
✗ Branch 1 not taken.
400432 dd_set_table_options(dd_table, m_table);
15156
15157
1/2
✓ Branch 0 taken 200215 times.
✗ Branch 1 not taken.
400430 dd_write_table(dd_space_id, dd_table, m_table);
15158
15159
2/2
✓ Branch 0 taken 585 times.
✓ Branch 1 taken 199630 times.
400430 if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) {
15160
1/2
✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
1170 ut_d(bool ret =) fts_create_common_dd_tables(m_table);
15161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
1170 ut_ad(ret);
15162
1/2
✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
1170 fts_create_index_dd_tables(m_table);
15163 }
15164
15165
2/4
✓ Branch 0 taken 200214 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 200216 times.
400430 ut_ad(dd_table_match(m_table, dd_table));
15166
15167 400432 return 0;
15168 858042 }
15169
15170 template int create_table_info_t::create_table_update_global_dd<dd::Table>(
15171 dd::Table *);
15172
15173 template int create_table_info_t::create_table_update_global_dd<dd::Partition>(
15174 dd::Partition *);
15175
15176 template <typename Table>
15177 815014 int innobase_basic_ddl::create_impl(THD *thd, const char *name, TABLE *form,
15178 HA_CREATE_INFO *create_info, Table *dd_tab,
15179 bool file_per_table, bool evictable,
15180 bool skip_strict, uint32_t old_flags,
15181 uint32_t old_flags2,
15182 const dd::Table *old_part_table) {
15183 815014 char norm_name[FN_REFLEN] = {'\0'}; /* {database}/{tablename} */
15184 815014 char remote_path[FN_REFLEN] = {'\0'}; /* Absolute path of table */
15185 815014 char tablespace[NAME_LEN] = {'\0'}; /* Tablespace name identifier */
15186 trx_t *trx;
15187
15188
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 407418 times.
815014 if (high_level_read_only &&
15189
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 84 times.
178 !(create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) {
15190 10 return HA_ERR_INNODB_READ_ONLY;
15191 }
15192
15193 /* Get the transaction associated with the current thd, or create one
15194 if not yet created */
15195
1/2
✓ Branch 0 taken 407503 times.
✗ Branch 1 not taken.
815004 trx = check_trx_exists(thd);
15196
15197
2/2
✓ Branch 0 taken 178595 times.
✓ Branch 1 taken 228908 times.
815006 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
15198
1/2
✓ Branch 0 taken 178594 times.
✗ Branch 1 not taken.
357190 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
15199 }
15200
15201
1/2
✓ Branch 0 taken 407502 times.
✗ Branch 1 not taken.
815004 create_table_info_t info(thd, form, create_info, norm_name, remote_path,
15202 tablespace, file_per_table, skip_strict, old_flags,
15203 old_flags2, false);
15204
15205 /* Initialize the object. */
15206
1/2
✓ Branch 0 taken 407503 times.
✗ Branch 1 not taken.
815004 int error = info.initialize();
15207
15208
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 407493 times.
815006 if (error != 0) {
15209 20 return (error);
15210 }
15211
15212 /* Prepare for create and validate options. */
15213
1/2
✓ Branch 0 taken 407492 times.
✗ Branch 1 not taken.
814986 error = info.prepare_create_table(name);
15214
15215
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 407160 times.
814984 if (error != 0) {
15216 664 return (error);
15217 }
15218
15219
5/7
✓ Branch 0 taken 224514 times.
✓ Branch 1 taken 182646 times.
✓ Branch 2 taken 3753 times.
✓ Branch 3 taken 403368 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3678 times.
✗ Branch 6 not taken.
814320 error = info.create_table(dd_tab != nullptr ? &dd_tab->table() : nullptr,
15220 old_part_table);
15221
2/2
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 406752 times.
814092 if (error) {
15222 588 goto cleanup;
15223 }
15224
15225
1/2
✓ Branch 0 taken 406749 times.
✗ Branch 1 not taken.
813504 error = info.create_table_update_global_dd(dd_tab);
15226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 406749 times.
813498 if (error) {
15227 goto cleanup;
15228 }
15229
15230
1/2
✓ Branch 0 taken 406752 times.
✗ Branch 1 not taken.
813498 error = info.create_table_update_dict();
15231
15232
9/10
✓ Branch 0 taken 352984 times.
✓ Branch 1 taken 53768 times.
✓ Branch 2 taken 306865 times.
✓ Branch 3 taken 46119 times.
✓ Branch 4 taken 306865 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 124222 times.
✓ Branch 7 taken 182643 times.
✓ Branch 8 taken 124222 times.
✓ Branch 9 taken 282530 times.
813504 if (evictable && !(info.is_temp_table() || info.is_intrinsic_temp_table())) {
15233
1/2
✓ Branch 0 taken 124222 times.
✗ Branch 1 not taken.
248444 info.detach();
15234 }
15235
15236 813504 return (error);
15237
15238 588 cleanup:
15239
7/8
✓ Branch 0 taken 294 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 291 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 287 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 290 times.
588 if (!info.is_intrinsic_temp_table() && info.is_temp_table()) {
15240
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 dict_sys_mutex_enter();
15241
15242
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 dict_table_t *table = dict_table_check_if_in_cache_low(norm_name);
15243
15244
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
8 if (table != nullptr) {
15245
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
8 for (dict_index_t *index = table->first_index(); index != nullptr;
15246
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 index = index->next()) {
15247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 ut_ad(index->space == table->space);
15248 4 page_no_t root = index->page;
15249 4 index->page = FIL_NULL;
15250
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 dict_drop_temporary_table_index(index, root);
15251 }
15252
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 dict_table_remove_from_cache(table);
15253 }
15254
15255
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 dict_sys_mutex_exit();
15256 } else {
15257 dict_table_t *intrinsic_table =
15258
2/4
✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 290 times.
✗ Branch 3 not taken.
580 thd_to_innodb_session(thd)->lookup_table_handler(info.table_name());
15259
15260
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 289 times.
580 if (intrinsic_table != nullptr) {
15261
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 thd_to_innodb_session(thd)->unregister_table_handler(info.table_name());
15262
15263 for (;;) {
15264 dict_index_t *index;
15265 2 index = UT_LIST_GET_FIRST(intrinsic_table->indexes);
15266
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 if (index == nullptr) {
15267 2 break;
15268 }
15269 rw_lock_free(&index->lock);
15270 UT_LIST_REMOVE(intrinsic_table->indexes, index);
15271 dict_mem_index_free(index);
15272 index = nullptr;
15273 }
15274
15275
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 dict_mem_table_free(intrinsic_table);
15276 2 intrinsic_table = nullptr;
15277 }
15278 }
15279
15280 588 return (error);
15281 }
15282
15283 template int innobase_basic_ddl::create_impl<dd::Table>(
15284 THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Table *, bool, bool,
15285 bool, uint32_t, uint32_t, const dd::Table *);
15286
15287 template int innobase_basic_ddl::create_impl<dd::Partition>(
15288 THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Partition *, bool, bool,
15289 bool, uint32_t, uint32_t, const dd::Table *);
15290
15291 template <typename Table>
15292 808344 int innobase_basic_ddl::delete_impl(THD *thd, const char *name,
15293 const Table *dd_tab, const TABLE *td) {
15294 808344 dberr_t error = DB_SUCCESS;
15295 char norm_name[FN_REFLEN];
15296
15297
2/6
✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 404172 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
808344 DBUG_EXECUTE_IF("test_normalize_table_name", test_normalize_table_name(););
15298
2/6
✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 404172 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
808344 DBUG_EXECUTE_IF("test_ut_format_name", test_ut_format_name(););
15299
15300 /* Strangely, MySQL passes the table name without the '.frm'
15301 extension, in contrast to ::create */
15302
2/4
✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 404172 times.
808344 if (!normalize_table_name(norm_name, name)) {
15303 /* purecov: begin inspected */
15304 ut_d(ut_error);
15305 ut_o(return (HA_ERR_TOO_LONG_PATH));
15306 /* purecov: end */
15307 }
15308
15309
1/2
✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
808344 innodb_session_t *&priv = thd_to_innodb_session(thd);
15310
1/2
✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
808344 dict_table_t *handler = priv->lookup_table_handler(norm_name);
15311
15312
2/2
✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 221529 times.
808344 if (handler != nullptr) {
15313
6/10
✓ Branch 0 taken 182643 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 185015 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 367658 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 185015 times.
✓ Branch 9 taken 182643 times.
1100602 for (auto index : handler->indexes) {
15314
2/2
✓ Branch 0 taken 113391 times.
✓ Branch 1 taken 71624 times.
370030 if (index->last_ins_cur) {
15315 /* last_ins_cur and last_sel_cur are allocated together, therefore only
15316 checking last_ins_cur before releasing mtr */
15317
1/2
✓ Branch 0 taken 113391 times.
✗ Branch 1 not taken.
226782 index->last_ins_cur->release();
15318
1/2
✓ Branch 0 taken 113391 times.
✗ Branch 1 not taken.
226782 index->last_sel_cur->release();
15319 }
15320 }
15321
2/2
✓ Branch 0 taken 221525 times.
✓ Branch 1 taken 4 times.
443058 } else if (srv_read_only_mode ||
15322
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 221523 times.
443050 srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
15323 12 return (HA_ERR_TABLE_READONLY);
15324 }
15325
15326
1/2
✓ Branch 0 taken 404166 times.
✗ Branch 1 not taken.
808332 trx_t *trx = check_trx_exists(thd);
15327
15328
1/2
✓ Branch 0 taken 404166 times.
✗ Branch 1 not taken.
808332 TrxInInnoDB trx_in_innodb(trx);
15329
15330 808332 ulint name_len = strlen(name);
15331
15332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 404166 times.
808332 ut_a(name_len < 1000);
15333
15334 /* Either the transaction is already flagged as a locking transaction
15335 or it hasn't been started yet. */
15336
15337
5/8
✓ Branch 0 taken 404166 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169712 times.
✓ Branch 3 taken 234454 times.
✓ Branch 4 taken 169712 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 404166 times.
808332 ut_a(!trx_is_started(trx) || trx->will_lock > 0);
15338
15339 /* We are doing a DDL operation. */
15340 808332 ++trx->will_lock;
15341
15342 808332 bool file_per_table = false;
15343
7/8
✓ Branch 0 taken 221523 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 221523 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 175375 times.
✓ Branch 5 taken 46148 times.
✓ Branch 6 taken 175375 times.
✓ Branch 7 taken 228791 times.
808332 if (dd_tab != nullptr && dd_tab->is_persistent()) {
15344 dict_table_t *tab;
15345
15346
1/2
✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
350750 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
15347
1/2
✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
350750 dd::cache::Dictionary_client::Auto_releaser releaser(client);
15348
15349
2/3
✓ Branch 0 taken 25934 times.
✓ Branch 1 taken 149441 times.
✗ Branch 2 not taken.
402618 int err = dd_table_open_on_dd_obj(
15350
1/2
✓ Branch 0 taken 25934 times.
✗ Branch 1 not taken.
51868 thd, client, dd_tab->table(),
15351
5/7
✓ Branch 0 taken 25934 times.
✓ Branch 1 taken 149441 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25934 times.
✓ Branch 4 taken 149441 times.
✓ Branch 5 taken 25934 times.
✗ Branch 6 not taken.
350750 (!dd_table_is_partitioned(dd_tab->table())
15352 ? nullptr
15353 : reinterpret_cast<const dd::Partition *>(dd_tab)),
15354 norm_name, tab, td);
15355
15356
2/4
✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 175375 times.
✗ Branch 3 not taken.
350750 if (err == 0 && tab != nullptr) {
15357
10/11
✓ Branch 0 taken 111759 times.
✓ Branch 1 taken 63616 times.
✓ Branch 2 taken 17120 times.
✓ Branch 3 taken 94639 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17120 times.
✓ Branch 6 taken 94639 times.
✓ Branch 7 taken 17120 times.
✓ Branch 8 taken 149441 times.
✓ Branch 9 taken 17120 times.
✓ Branch 10 taken 8814 times.
350750 if (tab->can_be_evicted && dd_table_is_partitioned(dd_tab->table())) {
15358
1/2
✓ Branch 0 taken 17120 times.
✗ Branch 1 not taken.
34240 dict_sys_mutex_enter();
15359
1/2
✓ Branch 0 taken 17120 times.
✗ Branch 1 not taken.
34240 dict_table_ddl_acquire(tab);
15360
1/2
✓ Branch 0 taken 17120 times.
✗ Branch 1 not taken.
34240 dict_sys_mutex_exit();
15361 }
15362
15363
1/2
✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
350750 file_per_table = dict_table_is_file_per_table(tab);
15364
1/2
✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
350750 dd_table_close(tab, thd, nullptr, false);
15365 }
15366 350750 }
15367
15368
1/2
✓ Branch 0 taken 404128 times.
✗ Branch 1 not taken.
808332 error = row_drop_table_for_mysql(norm_name, trx, true, handler);
15369
15370
3/4
✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 221485 times.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
808256 if (handler != nullptr && error == DB_SUCCESS) {
15371
1/2
✓ Branch 0 taken 182643 times.
✗ Branch 1 not taken.
365286 priv->unregister_table_handler(norm_name);
15372 }
15373
15374
4/4
✓ Branch 0 taken 404126 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 164322 times.
✓ Branch 3 taken 239804 times.
808256 if (error == DB_SUCCESS && file_per_table) {
15375
2/4
✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 164322 times.
✗ Branch 3 not taken.
328644 dd::Object_id dd_space_id = dd_first_index(dd_tab)->tablespace_id();
15376
1/2
✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
328644 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
15377
1/2
✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
328644 dd::cache::Dictionary_client::Auto_releaser releaser(client);
15378
15379
3/4
✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 164320 times.
328644 if (dd_drop_tablespace(client, dd_space_id)) {
15380 4 error = DB_ERROR;
15381 }
15382 328644 }
15383
15384
1/2
✓ Branch 0 taken 404128 times.
✗ Branch 1 not taken.
808256 return (convert_error_code_to_mysql(error, 0, nullptr));
15385 808256 }
15386
15387 template int innobase_basic_ddl::delete_impl<dd::Table>(THD *, const char *,
15388 const dd::Table *,
15389 const TABLE *);
15390
15391 template int innobase_basic_ddl::delete_impl<dd::Partition>(
15392 THD *, const char *, const dd::Partition *, const TABLE *);
15393
15394 template <typename Table>
15395 43630 int innobase_basic_ddl::rename_impl(THD *thd, const char *from, const char *to,
15396 const Table *from_table,
15397 const Table *to_table, const TABLE *td) {
15398 dberr_t error;
15399 char norm_to[FN_REFLEN];
15400 char norm_from[FN_REFLEN];
15401 43630 bool rename_file = false;
15402 43630 space_id_t space = SPACE_UNKNOWN;
15403 43630 dict_table_t *table = nullptr;
15404
15405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21815 times.
43630 ut_ad(!srv_read_only_mode);
15406
15407
3/6
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21815 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21815 times.
87260 if (!normalize_table_name(norm_to, to) ||
15408
2/4
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21815 times.
43630 !normalize_table_name(norm_from, from)) {
15409 /* purecov: begin inspected */
15410 ut_d(ut_error);
15411 ut_o(return (HA_ERR_TOO_LONG_PATH));
15412 /* purecov: end */
15413 }
15414
15415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21815 times.
43630 ut_ad(strcmp(norm_from, norm_to) != 0);
15416
15417
3/4
✓ Branch 0 taken 21557 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 21557 times.
✗ Branch 3 not taken.
43630 DEBUG_SYNC_C("innodb_rename_table_ready");
15418
15419
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 trx_t *trx = check_trx_exists(thd);
15420
15421
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
15422
15423
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 TrxInInnoDB trx_in_innodb(trx);
15424
15425 43630 ++trx->will_lock;
15426
15427
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 dd::cache::Dictionary_client *client = dd::get_dd_client(thd);
15428
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 dd::cache::Dictionary_client::Auto_releaser releaser(client);
15429
15430
2/3
✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14774 times.
✗ Branch 2 not taken.
57712 int err = dd_table_open_on_dd_obj(
15431
1/2
✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
14082 thd, client, from_table->table(),
15432
5/7
✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14774 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7041 times.
✓ Branch 4 taken 14774 times.
✓ Branch 5 taken 7041 times.
✗ Branch 6 not taken.
43630 (!dd_table_is_partitioned(from_table->table())
15433 ? nullptr
15434 : reinterpret_cast<const dd::Partition *>(from_table)),
15435 norm_from, table, td);
15436
2/4
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21815 times.
43630 if (err != 0 || table == nullptr) {
15437 error = DB_TABLE_NOT_FOUND;
15438 return (convert_error_code_to_mysql(error, 0, nullptr));
15439 }
15440
15441
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 rename_file = dict_table_is_file_per_table(table);
15442 43630 space = table->space;
15443
15444
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 if (row_is_mysql_tmp_table_name(norm_from) &&
15445
6/8
✓ Branch 0 taken 8487 times.
✓ Branch 1 taken 13328 times.
✓ Branch 2 taken 8487 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8487 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6578 times.
✓ Branch 7 taken 15237 times.
60604 !row_is_mysql_tmp_table_name(norm_to) &&
15446
4/7
✓ Branch 0 taken 1909 times.
✓ Branch 1 taken 6578 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8487 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1909 times.
16974 !dd_table_is_partitioned(from_table->table())) {
15447 13156 table->refresh_fk = true;
15448 }
15449
15450
5/7
✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14774 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7041 times.
✓ Branch 4 taken 14774 times.
✓ Branch 5 taken 7041 times.
✗ Branch 6 not taken.
43630 if (dd_table_is_partitioned(from_table->table())) {
15451
1/2
✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
14082 dict_sys_mutex_enter();
15452
1/2
✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
14082 dict_table_ddl_acquire(table);
15453
1/2
✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
14082 dict_sys_mutex_exit();
15454 }
15455
15456
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 dd_table_close(table, thd, nullptr, false);
15457
15458 /* Serialize data dictionary operations with dictionary mutex:
15459 no deadlocks can occur then in these operations. */
15460
15461
1/2
✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
43630 row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE);
15462
15463
3/5
✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14723 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6985 times.
✗ Branch 4 not taken.
43630 error = row_rename_table_for_mysql(norm_from, norm_to, &to_table->table(),
15464 trx, false);
15465
15466
1/2
✓ Branch 0 taken 21708 times.
✗ Branch 1 not taken.
43416 row_mysql_unlock_data_dictionary(trx);
15467
15468
4/4
✓ Branch 0 taken 21691 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 15701 times.
✓ Branch 3 taken 5990 times.
43416 if (error == DB_SUCCESS && rename_file) {
15469
1/2
✓ Branch 0 taken 15701 times.
✗ Branch 1 not taken.
31402 char *new_path = fil_space_get_first_path(space);
15470
15471
2/4
✓ Branch 0 taken 15701 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15701 times.
✗ Branch 3 not taken.
31402 auto dd_space_id = dd_first_index(to_table)->tablespace_id();
15472
15473
1/2
✓ Branch 0 taken 15701 times.
✗ Branch 1 not taken.
31402 error = dd_tablespace_rename(dd_space_id, false, norm_to, new_path);
15474
15475
2/2
✓ Branch 0 taken 15685 times.
✓ Branch 1 taken 16 times.
31402 if (new_path != nullptr) {
15476 31370 ut::free(new_path);
15477 }
15478 }
15479
15480
3/4
✓ Branch 0 taken 21450 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 21450 times.
✗ Branch 3 not taken.
43416 DEBUG_SYNC(thd, "after_innobase_rename_table");
15481
15482
2/2
✓ Branch 0 taken 21691 times.
✓ Branch 1 taken 17 times.
43416 if (error == DB_SUCCESS) {
15483 char errstr[512];
15484 dberr_t ret;
15485
15486
1/2
✓ Branch 0 taken 21691 times.
✗ Branch 1 not taken.
43382 ret = dict_stats_rename_table(norm_from, norm_to, errstr, sizeof(errstr));
15487
15488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21691 times.
43382 if (ret != DB_SUCCESS) {
15489 ib::error(ER_IB_MSG_566) << errstr;
15490
15491 push_warning(thd, Sql_condition::SL_WARNING, ER_LOCK_WAIT_TIMEOUT,
15492 errstr);
15493 }
15494 }
15495
15496 /* The duplicate key scenario was possible only for old DD since InnoDB
15497 would update it internally. With new DD, the rename conflict should be
15498 checked by server before diving into SE */
15499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21708 times.
43416 ut_ad(error != DB_DUPLICATE_KEY);
15500
15501
1/2
✓ Branch 0 taken 21708 times.
✗ Branch 1 not taken.
43416 return (convert_error_code_to_mysql(error, 0, nullptr));
15502 43416 }
15503
15504 template int innobase_basic_ddl::rename_impl<dd::Table>(THD *, const char *,
15505 const char *,
15506 const dd::Table *,
15507 const dd::Table *,
15508 const TABLE *);
15509
15510 template int innobase_basic_ddl::rename_impl<dd::Partition>(
15511 THD *, const char *, const char *, const dd::Partition *,
15512 const dd::Partition *, const TABLE *);
15513
15514 template <typename Table>
15515 105214 innobase_truncate<Table>::~innobase_truncate() {
15516
2/2
✓ Branch 0 taken 52605 times.
✓ Branch 1 taken 2 times.
105214 if (m_table != nullptr) {
15517 105210 dd_table_close(m_table, m_thd, nullptr, false);
15518 105210 m_table = nullptr;
15519 }
15520 105214 }
15521
15522 template innobase_truncate<dd::Table>::~innobase_truncate();
15523 template innobase_truncate<dd::Partition>::~innobase_truncate();
15524
15525 template <typename Table>
15526 105246 int innobase_truncate<Table>::open_table(dict_table_t *&innodb_table) {
15527
2/2
✓ Branch 0 taken 52580 times.
✓ Branch 1 taken 43 times.
105246 if (m_dd_table->table().is_persistent()) {
15528
1/2
✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
105160 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
15529
1/2
✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
105160 dd::cache::Dictionary_client::Auto_releaser releaser(client);
15530
15531
1/2
✓ Branch 0 taken 50068 times.
✗ Branch 1 not taken.
205296 int error = dd_table_open_on_dd_obj(
15532
2/4
✓ Branch 0 taken 2512 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2512 times.
✗ Branch 3 not taken.
105160 m_thd, client, m_dd_table->table(),
15533
3/4
✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2512 times.
✓ Branch 3 taken 50068 times.
105160 (dd_table_is_partitioned(m_dd_table->table())
15534 ? reinterpret_cast<const dd::Partition *>(m_dd_table)
15535 : nullptr),
15536
1/2
✓ Branch 0 taken 2512 times.
✗ Branch 1 not taken.
105160 m_name, innodb_table, m_form);
15537
15538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52580 times.
105160 if (error != 0) {
15539 return (error);
15540 }
15541
1/2
✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
105160 } else {
15542 86 innodb_table = dd_table_open_on_name_in_mem(m_name, false);
15543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
86 ut_ad(innodb_table->is_temporary());
15544 }
15545
15546 105246 m_table = innodb_table;
15547
15548 105246 return (0);
15549 }
15550
15551 template int innobase_truncate<dd::Table>::open_table(
15552 dict_table_t *&innodb_table);
15553 template int innobase_truncate<dd::Partition>::open_table(
15554 dict_table_t *&innodb_table);
15555
15556 template <typename Table>
15557 104330 int innobase_truncate<Table>::prepare() {
15558 104330 int error = 0;
15559
15560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52165 times.
104330 if (m_table == nullptr) {
15561 error = open_table(m_table);
15562
15563 if (error != 0) {
15564 return (error);
15565 }
15566 }
15567
15568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52165 times.
104330 ut_ad(m_table != nullptr);
15569
15570
1/2
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
104330 m_trx = check_trx_exists(m_thd);
15571
1/2
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
104330 m_file_per_table = dict_table_is_file_per_table(m_table);
15572 104330 m_flags = m_table->flags;
15573 104330 m_flags2 = m_table->flags2;
15574
15575
1/2
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
104330 update_create_info_from_table(&m_create_info, m_form);
15576
15577
1/2
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
104330 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
15578
1/2
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
104330 dd::cache::Dictionary_client::Auto_releaser releaser(client);
15579
15580 /* Get the autoextend_size attribute value for the table being
15581 truncated. This values will be used to create the new table as
15582 part of truncate. */
15583 104330 uint64_t autoextend_size{};
15584
15585
2/4
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52165 times.
✗ Branch 3 not taken.
104330 dd::Object_id space_id = dd_first_index(m_dd_table)->tablespace_id();
15586
15587
2/2
✓ Branch 0 taken 49293 times.
✓ Branch 1 taken 2872 times.
104330 if (m_file_per_table) {
15588
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 dd_get_tablespace_size_option(client, space_id, &autoextend_size);
15589 }
15590
15591 104330 m_create_info.m_implicit_tablespace_autoextend_size = autoextend_size;
15592
15593 104330 m_create_info.tablespace = nullptr;
15594
3/4
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 52122 times.
104330 if (m_table->is_temporary()) {
15595 86 m_create_info.options |= HA_LEX_CREATE_TMP_TABLE;
15596 } else {
15597
2/2
✓ Branch 0 taken 1787 times.
✓ Branch 1 taken 50335 times.
104244 if (m_table->tablespace != nullptr) {
15598
1/2
✓ Branch 0 taken 1787 times.
✗ Branch 1 not taken.
3574 m_create_info.tablespace = mem_strdup(m_table->tablespace);
15599 }
15600 }
15601
15602 104330 m_create_info.key_block_size = m_form->s->key_block_size;
15603
15604
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 52145 times.
104330 if (m_table->data_dir_path != nullptr) {
15605
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
40 m_create_info.data_file_name = mem_strdup(m_table->data_dir_path);
15606 } else {
15607 104290 m_create_info.data_file_name = nullptr;
15608 }
15609
15610
2/2
✓ Branch 0 taken 22763 times.
✓ Branch 1 taken 29402 times.
104330 if (m_table->can_be_evicted) {
15611
1/2
✓ Branch 0 taken 22763 times.
✗ Branch 1 not taken.
45526 dict_sys_mutex_enter();
15612
1/2
✓ Branch 0 taken 22763 times.
✗ Branch 1 not taken.
45526 dict_table_ddl_acquire(m_table);
15613
1/2
✓ Branch 0 taken 22763 times.
✗ Branch 1 not taken.
45526 dict_sys_mutex_exit();
15614 }
15615
15616
2/2
✓ Branch 0 taken 51690 times.
✓ Branch 1 taken 475 times.
104330 if (!dict_table_has_autoinc_col(m_table)) {
15617 103380 m_keep_autoinc = false;
15618 }
15619
15620 104330 return (error);
15621 104330 }
15622
15623 template <typename Table>
15624 104330 int innobase_truncate<Table>::truncate() {
15625 104330 int error = 0;
15626 104330 bool reset = false;
15627 104330 uint64_t autoinc = 0;
15628 104330 uint64_t autoinc_persisted = 0;
15629
15630 /* Rename tablespace file to avoid existing file in create. */
15631
2/2
✓ Branch 0 taken 49293 times.
✓ Branch 1 taken 2872 times.
104330 if (m_file_per_table) {
15632 98586 error = rename_tablespace();
15633 }
15634
15635
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52160 times.
104324 DBUG_EXECUTE_IF("ib_truncate_fail_after_rename", error = HA_ERR_GENERIC;);
15636
15637
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52159 times.
104324 if (error != 0) {
15638 6 return (error);
15639 }
15640
15641
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 52108 times.
104318 if (m_keep_autoinc) {
15642 102 autoinc_persisted = m_table->autoinc_persisted;
15643 102 autoinc = m_table->autoinc;
15644 }
15645
15646 104318 dd_table_close(m_table, m_thd, nullptr, false);
15647 104318 m_table = nullptr;
15648
15649
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52158 times.
104318 DBUG_EXECUTE_IF("ib_truncate_crash_after_rename", DBUG_SUICIDE(););
15650
15651 104316 error = innobase_basic_ddl::delete_impl(m_thd, m_name, m_dd_table, nullptr);
15652
15653
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52153 times.
104310 DBUG_EXECUTE_IF("ib_truncate_fail_after_delete", error = HA_ERR_GENERIC;);
15654
15655
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52153 times.
104310 if (error != 0) {
15656 4 return (error);
15657 }
15658
15659
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52152 times.
104306 DBUG_EXECUTE_IF("ib_truncate_crash_after_drop_old_table", DBUG_SUICIDE(););
15660
15661
2/2
✓ Branch 0 taken 52109 times.
✓ Branch 1 taken 43 times.
104304 if (m_dd_table->is_persistent()) {
15662 104218 m_dd_table->set_se_private_id(dd::INVALID_OBJECT_ID);
15663
6/10
✓ Branch 0 taken 52109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52109 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 52109 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 66745 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 66745 times.
✓ Branch 9 taken 52109 times.
341926 for (auto dd_index : *m_dd_table->indexes()) {
15664
2/4
✓ Branch 0 taken 66745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66745 times.
✗ Branch 3 not taken.
133490 dd_index->se_private_data().clear();
15665 }
15666 }
15667
15668 104304 if (dd_table_is_partitioned(m_dd_table->table()) &&
15669
4/6
✓ Branch 0 taken 2056 times.
✓ Branch 1 taken 50096 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 52152 times.
104304 m_create_info.tablespace != nullptr &&
15670 m_dd_table->tablespace_id() == dd::INVALID_OBJECT_ID) {
15671 /* Don't change the tablespace if it's a partitioned table,
15672 so temporarily set the tablespace_id as an explicit one
15673 to make it consistent with info->tablespace */
15674 m_dd_table->set_tablespace_id(dd_first_index(m_dd_table)->tablespace_id());
15675 reset = true;
15676 }
15677
15678 104304 m_trx->in_truncate = true;
15679 104304 bool inherit_metadata = false;
15680 104304 if (dd_table_has_instant_cols(m_dd_table->table()) &&
15681
8/8
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 52097 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 52137 times.
104304 dd_table_is_partitioned(m_dd_table->table()) && !m_table_truncate) {
15682 /* For a partition table, if this is not a full table truncate, and first
15683 partition is getting truncated, make sure INSTANT metadata is inherited. */
15684 30 inherit_metadata = true;
15685 }
15686
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 52137 times.
104304 error = innobase_basic_ddl::create_impl(
15687 104304 m_thd, m_name, m_form, &m_create_info, m_dd_table, m_file_per_table,
15688 false, true, m_flags, m_flags2,
15689 30 inherit_metadata ? &m_dd_table->table() : nullptr);
15690 104292 m_trx->in_truncate = false;
15691
15692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52146 times.
104292 if (reset) {
15693 m_dd_table->set_tablespace_id(dd::INVALID_OBJECT_ID);
15694 }
15695
15696
1/2
✓ Branch 0 taken 52146 times.
✗ Branch 1 not taken.
104292 if (error == 0) {
15697 104292 dict_sys_mutex_enter();
15698 104292 m_table = dict_table_check_if_in_cache_low(m_name);
15699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52146 times.
104292 ut_ad(m_table != nullptr);
15700 104292 m_table->acquire();
15701
15702
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 52096 times.
104292 if (m_keep_autoinc) {
15703 100 m_table->autoinc_persisted = autoinc_persisted;
15704 100 m_table->autoinc = autoinc;
15705 }
15706
15707 104292 dict_sys_mutex_exit();
15708 }
15709
15710
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52144 times.
104292 DBUG_EXECUTE_IF("ib_truncate_fail_after_create_new_table",
15711 error = HA_ERR_GENERIC;);
15712
15713
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52145 times.
104292 DBUG_EXECUTE_IF("ib_truncate_crash_after_create_new_table", DBUG_SUICIDE(););
15714
15715 104290 return (error);
15716 }
15717
15718 template <typename Table>
15719 98586 int innobase_truncate<Table>::rename_tablespace() {
15720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49293 times.
98586 ut_ad(m_table != nullptr);
15721
2/4
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49293 times.
98586 ut_ad(dict_table_is_file_per_table(m_table));
15722
2/4
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49293 times.
98586 ut_ad(!m_table->is_temporary());
15723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49293 times.
98586 ut_ad(m_table->trunc_name.m_name == nullptr);
15724
15725
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 uint64_t old_size = mem_heap_get_size(m_table->heap);
15726 197172 char *temp_name = dict_mem_create_temporary_tablename(
15727
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 m_table->heap, m_table->name.m_name, m_table->id);
15728
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 uint64_t new_size = mem_heap_get_size(m_table->heap);
15729
15730
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 dict_sys_mutex_enter();
15731 98586 dict_sys->size += new_size - old_size;
15732
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 dict_sys_mutex_exit();
15733
15734 98586 std::string new_path;
15735
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 char *old_path = fil_space_get_first_path(m_table->space);
15736
15737
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 49273 times.
98586 if (DICT_TF_HAS_DATA_DIR(m_table->flags)) {
15738
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 new_path = Fil_path::make_new_path(old_path, temp_name, IBD);
15739 } else {
15740
2/4
✓ Branch 0 taken 49273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49273 times.
✗ Branch 3 not taken.
98546 char *ptr = Fil_path::make_ibd_from_table_name(temp_name);
15741
1/2
✓ Branch 0 taken 49273 times.
✗ Branch 1 not taken.
98546 new_path.assign(ptr);
15742 98546 ut::free(ptr);
15743 }
15744
15745 /* New filepath must not exist. */
15746
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 dberr_t err = fil_rename_tablespace_check(m_table->space, old_path,
15747 new_path.c_str(), false);
15748
15749
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 if (err == DB_SUCCESS) {
15750
1/2
✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
98586 dict_sys_mutex_enter();
15751
1/2
✓ Branch 0 taken 49290 times.
✗ Branch 1 not taken.
98586 err = fil_rename_tablespace(m_table->space, old_path, temp_name,
15752 new_path.c_str());
15753
1/2
✓ Branch 0 taken 49290 times.
✗ Branch 1 not taken.
98580 dict_sys_mutex_exit();
15754
15755
2/2
✓ Branch 0 taken 49289 times.
✓ Branch 1 taken 1 times.
98580 if (err == DB_SUCCESS) {
15756 98578 m_table->trunc_name.m_name = temp_name;
15757 }
15758 }
15759
15760 98580 ut::free(old_path);
15761
15762
1/2
✓ Branch 0 taken 49290 times.
✗ Branch 1 not taken.
197160 return (convert_error_code_to_mysql(err, m_table->flags, nullptr));
15763 98580 }
15764
15765 template <typename Table>
15766 104300 void innobase_truncate<Table>::cleanup() {
15767
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52148 times.
104300 if (m_table == nullptr) {
15768 4 m_table = dd_table_open_on_name_in_mem(m_name, false);
15769 }
15770
15771
2/2
✓ Branch 0 taken 52148 times.
✓ Branch 1 taken 2 times.
104300 if (m_table != nullptr) {
15772 104296 m_table->trunc_name.m_name = nullptr;
15773 }
15774
15775 104300 char *tablespace = const_cast<char *>(m_create_info.tablespace);
15776 104300 char *data_file_name = const_cast<char *>(m_create_info.data_file_name);
15777
15778 104300 ut::free(tablespace);
15779 104300 ut::free(data_file_name);
15780 104300 }
15781
15782 template <typename Table>
15783 104286 int innobase_truncate<Table>::load_fk() {
15784
5/7
✓ Branch 0 taken 2055 times.
✓ Branch 1 taken 50088 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2055 times.
✓ Branch 4 taken 50088 times.
✓ Branch 5 taken 2055 times.
✗ Branch 6 not taken.
104286 if (dd_table_is_partitioned(m_dd_table->table())) {
15785 4110 return (0);
15786 }
15787
15788 100176 int error = 0;
15789
1/2
✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
100176 dict_names_t fk_tables;
15790
1/2
✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
100176 dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd);
15791
1/2
✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
100176 dd::cache::Dictionary_client::Auto_releaser releaser(client);
15792
15793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50088 times.
100176 ut_ad(m_table != nullptr);
15794 100176 error =
15795
1/2
✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
100176 dd_table_check_for_child(client, m_table->name.m_name, nullptr, m_table,
15796 true, DICT_ERR_IGNORE_NONE, &fk_tables);
15797
15798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50088 times.
100176 ut_ad(fk_tables.empty());
15799
15800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50088 times.
100176 if (error != DB_SUCCESS) {
15801 push_warning_printf(m_thd, Sql_condition::SL_WARNING,
15802 HA_ERR_CANNOT_ADD_FOREIGN,
15803 "Truncate table '%s' failed to load some"
15804 " foreign key constraints.",
15805 m_name);
15806 } else {
15807 100176 error = 0;
15808 }
15809
15810 100176 return (error);
15811 }
15812
15813 template <typename Table>
15814 104330 int innobase_truncate<Table>::exec() {
15815 104330 int error = 0;
15816
15817 104330 error = prepare();
15818
15819
1/2
✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
104330 if (error == 0) {
15820 104330 error = truncate();
15821 }
15822
15823 104300 cleanup();
15824
15825
2/2
✓ Branch 0 taken 52143 times.
✓ Branch 1 taken 7 times.
104300 if (error == 0) {
15826 104286 error = load_fk();
15827 }
15828
15829
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52149 times.
104300 DBUG_EXECUTE_IF("ib_truncate_crash_after_innodb_complete", DBUG_SUICIDE(););
15830
15831
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52148 times.
104298 DBUG_EXECUTE_IF("ib_truncate_rollback_test", error = HA_ERR_GENERIC;);
15832
15833 104298 return (error);
15834 }
15835
15836 template int innobase_truncate<dd::Table>::exec();
15837 template int innobase_truncate<dd::Partition>::exec();
15838
15839 /** Check if a column is the only column in an index.
15840 @param[in] index data dictionary index
15841 @param[in] column the column to look for
15842 @return whether the column is the only column in the index */
15843 32 static bool dd_is_only_column(const dd::Index *index,
15844 const dd::Column *column) {
15845
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1 times.
63 return (index->elements().size() == 1 &&
15846
6/10
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 31 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 2 times.
63 &(*index->elements().begin())->column() == column);
15847 }
15848
15849 /** Add hidden columns and indexes to an InnoDB table definition.
15850 @param[in,out] dd_table data dictionary cache object
15851 @return error number
15852 @retval 0 on success */
15853 626007 int ha_innobase::get_extra_columns_and_keys(const HA_CREATE_INFO *,
15854 const List<Create_field> *,
15855 const KEY *, uint,
15856 dd::Table *dd_table) {
15857
1/2
✓ Branch 0 taken 626023 times.
✗ Branch 1 not taken.
626007 DBUG_TRACE;
15858
1/2
✓ Branch 0 taken 626019 times.
✗ Branch 1 not taken.
626023 THD *thd = ha_thd();
15859 626019 dd::Index *primary = nullptr;
15860 626019 bool has_fulltext = false;
15861 626019 const dd::Index *fts_doc_id_index = nullptr;
15862
15863
6/10
✓ Branch 0 taken 626012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 626018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 626014 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1355315 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1355315 times.
✓ Branch 9 taken 626018 times.
1981334 for (dd::Index *i : *dd_table->indexes()) {
15864 /* The name "PRIMARY" is reserved for the PRIMARY KEY */
15865
4/8
✓ Branch 0 taken 1355315 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1355315 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1355315 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1355315 times.
1355315 ut_ad((i->type() == dd::Index::IT_PRIMARY) ==
15866 !my_strcasecmp(system_charset_info, i->name().c_str(),
15867 primary_key_name));
15868
15869
4/6
✓ Branch 0 taken 1355315 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1355315 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
✓ Branch 5 taken 1355256 times.
1355315 if (!my_strcasecmp(system_charset_info, i->name().c_str(),
15870 FTS_DOC_ID_INDEX_NAME)) {
15871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 ut_ad(!fts_doc_id_index);
15872
2/4
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
59 ut_ad(i->type() != dd::Index::IT_PRIMARY);
15873 59 fts_doc_id_index = i;
15874 }
15875
15876
4/8
✓ Branch 0 taken 1355315 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1226 times.
✓ Branch 5 taken 1351779 times.
✓ Branch 6 taken 2310 times.
✗ Branch 7 not taken.
1355315 switch (i->algorithm()) {
15877 case dd::Index::IA_SE_SPECIFIC:
15878 ut_d(ut_error);
15879 ut_o(break);
15880 case dd::Index::IA_HASH:
15881 /* This is currently blocked
15882 by ha_innobase::is_index_algorithm_supported(). */
15883 ut_d(ut_error);
15884 ut_o(break);
15885 1226 case dd::Index::IA_RTREE:
15886
2/4
✓ Branch 0 taken 1226 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1226 times.
✗ Branch 3 not taken.
1226 if (i->type() == dd::Index::IT_SPATIAL) {
15887 1226 continue;
15888 }
15889 ut_d(ut_error);
15890 ut_o(break);
15891 1351779 case dd::Index::IA_BTREE:
15892
4/7
✓ Branch 0 taken 1351779 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 455694 times.
✓ Branch 3 taken 419273 times.
✓ Branch 4 taken 476812 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1351779 switch (i->type()) {
15893 455694 case dd::Index::IT_PRIMARY:
15894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 455694 times.
455694 ut_ad(!primary);
15895
4/8
✓ Branch 0 taken 455694 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 455694 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 455694 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 455694 times.
455694 ut_ad(i == *dd_table->indexes()->begin());
15896 455694 primary = i;
15897 455694 continue;
15898 419273 case dd::Index::IT_UNIQUE:
15899
7/8
✓ Branch 0 taken 38995 times.
✓ Branch 1 taken 380278 times.
✓ Branch 2 taken 38995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37366 times.
✓ Branch 5 taken 1629 times.
✓ Branch 6 taken 37366 times.
✓ Branch 7 taken 381907 times.
419273 if (primary == nullptr && i->is_candidate_key()) {
15900 37366 primary = i;
15901
4/8
✓ Branch 0 taken 37366 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37366 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37366 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 37366 times.
37366 ut_ad(*dd_table->indexes()->begin() == i);
15902 }
15903 419273 continue;
15904 476812 case dd::Index::IT_MULTIPLE:
15905 476812 continue;
15906 case dd::Index::IT_FULLTEXT:
15907 case dd::Index::IT_SPATIAL:
15908 ut_d(ut_error);
15909 }
15910 break;
15911 2310 case dd::Index::IA_FULLTEXT:
15912
2/4
✓ Branch 0 taken 2310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2310 times.
✗ Branch 3 not taken.
2310 if (i->type() == dd::Index::IT_FULLTEXT) {
15913 2310 has_fulltext = true;
15914 2310 continue;
15915 }
15916 ut_d(ut_error);
15917 ut_o(break);
15918 }
15919
15920 my_error(ER_UNSUPPORTED_INDEX_ALGORITHM, MYF(0), i->name().c_str());
15921 return ER_UNSUPPORTED_INDEX_ALGORITHM;
15922 }
15923
15924
2/2
✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 624858 times.
626018 if (has_fulltext) {
15925 /* Add FTS_DOC_ID_INDEX(FTS_DOC_ID) if needed */
15926 const dd::Column *fts_doc_id =
15927
1/2
✓ Branch 0 taken 1160 times.
✗ Branch 1 not taken.
1160 dd_find_column(dd_table, FTS_DOC_ID_COL_NAME);
15928
15929
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1126 times.
1160 if (fts_doc_id_index) {
15930
3/6
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
34 switch (fts_doc_id_index->type()) {
15931 case dd::Index::IT_PRIMARY:
15932 /* PRIMARY!=FTS_DOC_ID_INDEX */
15933 ut_ad(!"wrong fts_doc_id_index");
15934 [[fallthrough]];
15935 case dd::Index::IT_UNIQUE:
15936 /* We already checked for this. */
15937
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 ut_ad(fts_doc_id_index->algorithm() == dd::Index::IA_BTREE);
15938
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 3 times.
32 if (dd_is_only_column(fts_doc_id_index, fts_doc_id)) {
15939 29 break;
15940 }
15941 [[fallthrough]];
15942 case dd::Index::IT_MULTIPLE:
15943 case dd::Index::IT_FULLTEXT:
15944 case dd::Index::IT_SPATIAL:
15945
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0),
15946
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 fts_doc_id_index->name().c_str());
15947
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_NAME_FOR_INDEX,
15948 " InnoDB: Index name " FTS_DOC_ID_INDEX_NAME
15949 " is reserved"
15950 " for UNIQUE INDEX(" FTS_DOC_ID_COL_NAME
15951 ") for "
15952 " FULLTEXT Document ID indexing.");
15953 5 return ER_INNODB_FT_WRONG_DOCID_INDEX;
15954 }
15955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 ut_ad(fts_doc_id);
15956 }
15957
15958
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 1069 times.
1155 if (fts_doc_id) {
15959
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 if (fts_doc_id->type() != dd::enum_column_types::LONGLONG ||
15960
7/8
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 68 times.
154 fts_doc_id->is_nullable() ||
15961
3/6
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
68 fts_doc_id->name() != FTS_DOC_ID_COL_NAME) {
15962
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0),
15963
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 fts_doc_id->name().c_str());
15964
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_COLUMN_NAME,
15965 " InnoDB: Column name " FTS_DOC_ID_COL_NAME
15966 " is reserved for"
15967 " FULLTEXT Document ID indexing.");
15968 18 return ER_INNODB_FT_WRONG_DOCID_COLUMN;
15969 }
15970 } else {
15971 /* Add hidden FTS_DOC_ID column */
15972
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 dd::Column *col = dd_table->add_column();
15973
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 col->set_hidden(dd::Column::enum_hidden_type::HT_HIDDEN_SE);
15974
2/4
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1069 times.
✗ Branch 3 not taken.
1069 col->set_name(FTS_DOC_ID_COL_NAME);
15975
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 col->set_type(dd::enum_column_types::LONGLONG);
15976
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 col->set_nullable(false);
15977
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 col->set_unsigned(true);
15978
1/2
✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
1069 col->set_collation_id(1);
15979 1069 fts_doc_id = col;
15980 }
15981
15982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1137 times.
1137 ut_ad(fts_doc_id);
15983
15984
2/2
✓ Branch 0 taken 1109 times.
✓ Branch 1 taken 28 times.
1137 if (fts_doc_id_index == nullptr) {
15985
2/4
✓ Branch 0 taken 1109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1109 times.
✗ Branch 3 not taken.
1109 dd_set_hidden_unique_index(dd_table->add_index(), FTS_DOC_ID_INDEX_NAME,
15986 fts_doc_id);
15987 }
15988 }
15989
15990
2/2
✓ Branch 0 taken 132944 times.
✓ Branch 1 taken 493051 times.
625995 if (primary == nullptr) {
15991
1/2
✓ Branch 0 taken 132960 times.
✗ Branch 1 not taken.
132944 dd::Column *db_row_id = dd_add_hidden_column(
15992 dd_table, "DB_ROW_ID", DATA_ROW_ID_LEN, dd::enum_column_types::INT24);
15993
15994
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 132958 times.
132960 if (db_row_id == nullptr) {
15995 2 return ER_WRONG_COLUMN_NAME;
15996 }
15997
15998
2/4
✓ Branch 0 taken 132954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132957 times.
✗ Branch 3 not taken.
132958 primary = dd_set_hidden_unique_index(dd_table->add_first_index(),
15999 primary_key_name, db_row_id);
16000 }
16001
16002 /* Add PRIMARY KEY columns to each secondary index, including:
16003 1. all PRIMARY KEY column prefixes
16004 2. full PRIMARY KEY columns which don't exist in the secondary index */
16005
16006 std::vector<const dd::Index_element *,
16007 ut::allocator<const dd::Index_element *>>
16008
1/2
✓ Branch 0 taken 625989 times.
✗ Branch 1 not taken.
1252006 pk_elements;
16009
16010
6/10
✓ Branch 0 taken 625993 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 625988 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 625994 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1489319 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1489307 times.
✓ Branch 9 taken 625993 times.
2115308 for (dd::Index *index : *dd_table->indexes()) {
16011
2/2
✓ Branch 0 taken 625992 times.
✓ Branch 1 taken 863327 times.
1489319 if (index == primary) {
16012 625992 continue;
16013 }
16014
16015 863327 pk_elements.clear();
16016
6/10
✓ Branch 0 taken 863327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 863327 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 863327 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1047345 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1047345 times.
✓ Branch 9 taken 863327 times.
1910672 for (const dd::Index_element *e : primary->elements()) {
16017
5/6
✓ Branch 0 taken 1047345 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029333 times.
✓ Branch 3 taken 18012 times.
✓ Branch 4 taken 914568 times.
✓ Branch 5 taken 114765 times.
2076678 if (e->is_prefix() ||
16018
1/2
✓ Branch 0 taken 1029333 times.
✗ Branch 1 not taken.
1029333 std::search_n(
16019
4/8
✓ Branch 0 taken 1029333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1029333 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1029333 times.
✗ Branch 7 not taken.
1029333 index->elements().begin(), index->elements().end(), 1, e,
16020 1591185 [](const dd::Index_element *ie, const dd::Index_element *e) {
16021 1591185 return (&ie->column() == &e->column());
16022
4/6
✓ Branch 0 taken 1029333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 932580 times.
✓ Branch 5 taken 114765 times.
3106011 }) == index->elements().end()) {
16023
1/2
✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
932580 pk_elements.push_back(e);
16024 }
16025 }
16026
16027
2/2
✓ Branch 0 taken 932580 times.
✓ Branch 1 taken 863327 times.
1795907 for (const dd::Index_element *e : pk_elements) {
16028
2/4
✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932580 times.
✗ Branch 3 not taken.
932580 auto ie = index->add_element(const_cast<dd::Column *>(&e->column()));
16029
1/2
✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
932580 ie->set_hidden(true);
16030
2/4
✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932580 times.
✗ Branch 3 not taken.
932580 ie->set_order(e->order());
16031 }
16032 }
16033
16034 /* Add the InnoDB system columns DB_TRX_ID, DB_ROLL_PTR. */
16035
1/2
✓ Branch 0 taken 625998 times.
✗ Branch 1 not taken.
625993 dd::Column *db_trx_id = dd_add_hidden_column(
16036 dd_table, "DB_TRX_ID", DATA_TRX_ID_LEN, dd::enum_column_types::INT24);
16037
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 625995 times.
625998 if (db_trx_id == nullptr) {
16038 3 return ER_WRONG_COLUMN_NAME;
16039 }
16040
16041 dd::Column *db_roll_ptr =
16042
1/2
✓ Branch 0 taken 625996 times.
✗ Branch 1 not taken.
625995 dd_add_hidden_column(dd_table, "DB_ROLL_PTR", DATA_ROLL_PTR_LEN,
16043 dd::enum_column_types::LONGLONG);
16044
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 625993 times.
625996 if (db_roll_ptr == nullptr) {
16045 3 return ER_WRONG_COLUMN_NAME;
16046 }
16047
16048
1/2
✓ Branch 0 taken 625993 times.
✗ Branch 1 not taken.
625993 dd_add_hidden_element(primary, db_trx_id);
16049
1/2
✓ Branch 0 taken 625992 times.
✗ Branch 1 not taken.
625993 dd_add_hidden_element(primary, db_roll_ptr);
16050
16051 /* Add all non-virtual columns to the clustered index,
16052 unless they already part of the PRIMARY KEY. */
16053
16054 625992 for (const dd::Column *c :
16055
6/10
✓ Branch 0 taken 625993 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 625993 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 625992 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6503069 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6503068 times.
✓ Branch 9 taken 625992 times.
7755059 const_cast<const dd::Table *>(dd_table)->columns()) {
16056
8/10
✓ Branch 0 taken 6503070 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5117063 times.
✓ Branch 3 taken 1386007 times.
✓ Branch 4 taken 5117060 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9220 times.
✓ Branch 7 taken 5107840 times.
✓ Branch 8 taken 1395229 times.
✓ Branch 9 taken 5107838 times.
6503069 if (c->is_se_hidden() || c->is_virtual()) {
16057 1395229 continue;
16058 }
16059
16060
5/10
✓ Branch 0 taken 5107847 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5107838 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5107847 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5107845 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5107845 times.
✗ Branch 9 not taken.
5107846 if (std::search_n(primary->elements().begin(), primary->elements().end(), 1,
16061 70101815 c, [](const dd::Index_element *e, const dd::Column *c) {
16062
4/4
✓ Branch 0 taken 6291892 times.
✓ Branch 1 taken 63809933 times.
✓ Branch 2 taken 809614 times.
✓ Branch 3 taken 5482278 times.
70101815 return (!e->is_prefix() && &e->column() == c);
16063
4/6
✓ Branch 0 taken 5107840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5107846 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4298231 times.
✓ Branch 5 taken 809613 times.
10215683 }) == primary->elements().end()) {
16064
1/2
✓ Branch 0 taken 4298233 times.
✗ Branch 1 not taken.
4298231 dd_add_hidden_element(primary, c);
16065 }
16066 }
16067
16068 625992 return 0;
16069 626023 }
16070
16071 /** Set Engine specific data to dd::Table object for upgrade.
16072 @param[in,out] thd thread handle
16073 @param[in] db_name database name
16074 @param[in] table_name table name
16075 @param[in,out] dd_table data dictionary cache object
16076 @return 0 on success, non-zero on failure */
16077 3101 bool ha_innobase::upgrade_table(THD *thd, const char *db_name,
16078 const char *table_name, dd::Table *dd_table) {
16079 3101 return (dd_upgrade_table(thd, db_name, table_name, dd_table, table));
16080 }
16081
16082 /** Get storage-engine private data for a data dictionary table.
16083 @param[in,out] dd_table data dictionary table definition
16084 @param reset reset counters
16085 @retval true an error occurred
16086 @retval false success */
16087 24500 bool ha_innobase::get_se_private_data(dd::Table *dd_table, bool reset) {
16088 static uint n_tables = 0;
16089 static uint n_indexes = 0;
16090 static uint n_pages = 4;
16091
16092 /* Reset counters on second create during upgrade. */
16093
2/2
✓ Branch 0 taken 11960 times.
✓ Branch 1 taken 12540 times.
24500 if (reset) {
16094 11960 n_tables = 0;
16095 11960 n_indexes = 0;
16096 11960 n_pages = 4;
16097 // Also need to reset the set of DD table ids.
16098 11960 dict_sys_t::s_dd_table_ids.clear();
16099 }
16100 #ifdef UNIV_DEBUG
16101 24500 const uint n_indexes_old = n_indexes;
16102 #endif
16103
16104
1/2
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
24500 DBUG_TRACE;
16105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24500 times.
24500 assert(dd_table != nullptr);
16106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24500 times.
24500 assert(n_tables < innodb_dd_table_size);
16107
16108
3/6
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24500 times.
✗ Branch 5 not taken.
24500 if ((*(const_cast<const dd::Table *>(dd_table))->columns().begin())
16109
3/4
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6840 times.
✓ Branch 3 taken 17660 times.
24500 ->is_auto_increment()) {
16110
2/4
✓ Branch 0 taken 6840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6840 times.
✗ Branch 3 not taken.
6840 dd_set_autoinc(dd_table->se_private_data(), 0);
16111 }
16112
16113 #ifdef UNIV_DEBUG
16114 {
16115 /* These tables must not be partitioned. */
16116
2/4
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24500 times.
24500 assert(dd_table->partitions()->empty());
16117 }
16118
16119 24500 const innodb_dd_table_t &data = innodb_dd_table[n_tables];
16120 #endif
16121
16122
2/4
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24500 times.
24500 assert(dd_table->name() == data.name);
16123
16124
1/2
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
24500 dd_table->set_se_private_id(++n_tables);
16125
1/2
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
24500 dd_table->set_tablespace_id(dict_sys_t::s_dd_dict_space_id);
16126
16127 /* Set the table id for each column to be conform with the
16128 implementation in dd_write_table(). */
16129
6/10
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24500 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 203640 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 203640 times.
✓ Branch 9 taken 24500 times.
228140 for (auto dd_column : *dd_table->table().columns()) {
16130
3/6
✓ Branch 0 taken 203640 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 203640 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 203640 times.
✗ Branch 5 not taken.
203640 dd_column->se_private_data().set(dd_index_key_strings[DD_TABLE_ID],
16131 n_tables);
16132 }
16133
16134
6/10
✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24500 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 50340 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 50340 times.
✓ Branch 9 taken 24500 times.
74840 for (dd::Index *i : *dd_table->indexes()) {
16135
1/2
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
50340 i->set_tablespace_id(dict_sys_t::s_dd_dict_space_id);
16136
16137
3/4
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 926 times.
✓ Branch 3 taken 49414 times.
50340 if (fsp_is_inode_page(n_pages)) {
16138 926 ++n_pages;
16139
2/4
✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 926 times.
926 ut_ad(!fsp_is_inode_page(n_pages));
16140 }
16141
16142
1/2
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
50340 dd::Properties &p = i->se_private_data();
16143
16144
2/4
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
50340 p.set(dd_index_key_strings[DD_INDEX_ROOT], n_pages++);
16145
2/4
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
50340 p.set(dd_index_key_strings[DD_INDEX_ID], ++n_indexes);
16146
2/4
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
50340 p.set(dd_index_key_strings[DD_INDEX_TRX_ID], 0);
16147
2/4
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
50340 p.set(dd_index_key_strings[DD_INDEX_SPACE_ID], dict_sys_t::s_dict_space_id);
16148
2/4
✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
50340 p.set(dd_index_key_strings[DD_TABLE_ID], n_tables);
16149 }
16150
16151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24500 times.
24500 assert(n_indexes - n_indexes_old == data.n_indexes);
16152
16153 24500 return false;
16154 24500 }
16155
16156 /** Create an InnoDB table.
16157 @param[in] name table name in filename-safe encoding
16158 @param[in] form table structure
16159 @param[in] create_info more information on the table
16160 @param[in,out] table_def dd::Table describing table to be
16161 created. Can be adjusted by SE, the changes will be saved into data-dictionary
16162 at statement commit time.
16163 @return error number
16164 @retval 0 on success */
16165 403769 int ha_innobase::create(const char *name, TABLE *form,
16166 HA_CREATE_INFO *create_info, dd::Table *table_def) {
16167 403769 THD *thd = ha_thd();
16168
16169 403769 adjust_encryption_options(create_info, table_def);
16170
16171
2/2
✓ Branch 0 taken 50115 times.
✓ Branch 1 taken 353654 times.
403769 if (thd_sql_command(thd) == SQLCOM_TRUNCATE) {
16172 50115 return (truncate_impl(name, form, table_def));
16173 }
16174
16175 353654 trx_t *trx = check_trx_exists(thd);
16176
16177
2/2
✓ Branch 0 taken 124787 times.
✓ Branch 1 taken 228867 times.
353654 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
16178 124787 innobase_register_trx(ht, thd, trx);
16179 }
16180
16181 /* Determine if this CREATE TABLE will be making a file-per-table
16182 tablespace. Note that "srv_file_per_table" is not under
16183 dict_sys mutex protection, and could be changed while creating the
16184 table. So we read the current value here and make all further
16185 decisions based on this. */
16186 353653 return (innobase_basic_ddl::create_impl(ha_thd(), name, form, create_info,
16187 table_def, srv_file_per_table, true,
16188 353620 false, 0, 0, nullptr));
16189 }
16190
16191 /** Discards or imports an InnoDB tablespace.
16192 @param[in] discard true if discard, else import
16193 @param[in,out] table_def dd::Table describing table which
16194 tablespace is to be imported or discarded. Can be adjusted by SE,
16195 the changes will be saved into the data-dictionary at statement
16196 commit time.
16197 @return 0 == success, -1 == error */
16198
16199 1721 int ha_innobase::discard_or_import_tablespace(bool discard,
16200 dd::Table *table_def) {
16201
1/2
✓ Branch 0 taken 1721 times.
✗ Branch 1 not taken.
1721 DBUG_TRACE;
16202
16203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1721 times.
1721 ut_a(m_prebuilt->trx != nullptr);
16204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1721 times.
1721 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
16205
3/6
✓ Branch 0 taken 1721 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1721 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1721 times.
1721 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
16206
16207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1721 times.
1721 if (high_level_read_only) {
16208 return HA_ERR_TABLE_READONLY;
16209 }
16210
16211 1721 dict_table_t *dict_table = m_prebuilt->table;
16212
16213
3/4
✓ Branch 0 taken 1721 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1714 times.
1721 if (dict_table->is_temporary()) {
16214
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
16215 ER_CANNOT_DISCARD_TEMPORARY_TABLE);
16216
16217 7 return HA_ERR_TABLE_NEEDS_UPGRADE;
16218 }
16219
16220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1714 times.
1714 if (dict_table->space == TRX_SYS_SPACE) {
16221 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
16222 ER_TABLE_IN_SYSTEM_TABLESPACE, dict_table->name.m_name);
16223
16224 return HA_ERR_TABLE_NEEDS_UPGRADE;
16225 }
16226
16227
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1712 times.
1714 if (DICT_TF_HAS_SHARED_SPACE(dict_table->flags)) {
16228
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 my_printf_error(ER_NOT_ALLOWED_COMMAND,
16229 "InnoDB: Cannot %s table `%s` because it is in"
16230 " a general tablespace. It must be file-per-table.",
16231 MYF(0), discard ? "discard" : "import",
16232 dict_table->name.m_name);
16233
16234 2 return HA_ERR_NOT_ALLOWED_COMMAND;
16235 }
16236
16237
1/2
✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
1712 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
16238
16239
2/4
✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1712 times.
1712 if (trx_in_innodb.is_aborted()) {
16240 innobase_rollback(ht, m_user_thd, false);
16241
16242 return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd);
16243 }
16244
16245
1/2
✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
1712 trx_start_if_not_started(m_prebuilt->trx, true, UT_LOCATION_HERE);
16246
16247 /* Obtain an exclusive lock on the table. */
16248
2/2
✓ Branch 0 taken 894 times.
✓ Branch 1 taken 818 times.
1712 dberr_t err = row_mysql_lock_table(
16249
1/2
✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
1712 m_prebuilt->trx, dict_table, LOCK_X,
16250 discard ? "setting table lock for DISCARD TABLESPACE"
16251 : "setting table lock for IMPORT TABLESPACE");
16252
16253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1712 times.
1712 if (err != DB_SUCCESS) {
16254 /* unable to lock the table: do nothing */
16255 /* purecov: begin inspected */
16256 return convert_error_code_to_mysql(err, dict_table->flags, nullptr);
16257 /* purecov: end */
16258 }
16259
16260 /* Concurrent clone operation is not supported. */
16261 Clone_notify notifier(Clone_notify::Type::SPACE_IMPORT,
16262
1/2
✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
1712 dict_sys_t::s_invalid_space_id, false);
16263
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1710 times.
1712 if (notifier.failed()) {
16264 2 return notifier.get_error();
16265 }
16266
16267
2/2
✓ Branch 0 taken 893 times.
✓ Branch 1 taken 817 times.
1710 if (discard) {
16268 /* Discarding an already discarded tablespace should be an
16269 idempotent operation. Also, if the .ibd file is missing the
16270 user may want to set the DISCARD flag in order to IMPORT
16271 a new tablespace. */
16272
16273
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 876 times.
893 if (dict_table->ibd_file_missing) {
16274
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_WARN,
16275 ER_TABLESPACE_MISSING, dict_table->name.m_name);
16276 }
16277
16278 891 err = row_discard_tablespace_for_mysql(dict_table->name.m_name,
16279
1/2
✓ Branch 0 taken 891 times.
✗ Branch 1 not taken.
893 m_prebuilt->trx);
16280
16281
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 812 times.
817 } else if (!dict_table->ibd_file_missing) {
16282
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
10 ib::error(ER_IB_MSG_567)
16283
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 << "Unable to import tablespace " << dict_table->name
16284 << " because it already"
16285 " exists. Please DISCARD the tablespace"
16286
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 " before IMPORT.";
16287
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR,
16288 ER_TABLESPACE_EXISTS, dict_table->name.m_name);
16289
16290 5 return HA_ERR_TABLE_EXIST;
16291 } else {
16292
1/2
✓ Branch 0 taken 788 times.
✗ Branch 1 not taken.
812 err = row_import_for_mysql(dict_table, table_def, m_prebuilt);
16293
16294
2/2
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 216 times.
788 if (err == DB_SUCCESS) {
16295
1/2
✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
572 info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE |
16296 HA_STATUS_AUTO);
16297 }
16298 }
16299
16300 /* Set the TABLESPACE DISCARD flag in the table definition
16301 on disk. */
16302
2/2
✓ Branch 0 taken 1460 times.
✓ Branch 1 taken 219 times.
1679 if (err == DB_SUCCESS) {
16303
1/2
✓ Branch 0 taken 1460 times.
✗ Branch 1 not taken.
1460 dd_table_discard_tablespace(m_prebuilt->trx->mysql_thd, dict_table,
16304 table_def, discard);
16305 }
16306
16307
6/6
✓ Branch 0 taken 1460 times.
✓ Branch 1 taken 219 times.
✓ Branch 2 taken 572 times.
✓ Branch 3 taken 888 times.
✓ Branch 4 taken 571 times.
✓ Branch 5 taken 1108 times.
2251 if (err == DB_SUCCESS && !discard &&
16308
3/4
✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 571 times.
✓ Branch 3 taken 1 times.
572 dict_stats_is_persistent_enabled(dict_table)) {
16309 dberr_t ret;
16310
16311 /* Adjust the persistent statistics. */
16312
1/2
✓ Branch 0 taken 571 times.
✗ Branch 1 not taken.
571 ret = dict_stats_update(dict_table, DICT_STATS_RECALC_PERSISTENT);
16313
16314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 571 times.
571 if (ret != DB_SUCCESS) {
16315 push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_ALTER_INFO,
16316 "Error updating stats for table '%s'"
16317 " after table rebuild: %s",
16318 dict_table->name.m_name, ut_strerr(ret));
16319 }
16320 }
16321
16322
1/2
✓ Branch 0 taken 1679 times.
✗ Branch 1 not taken.
1679 return convert_error_code_to_mysql(err, dict_table->flags, nullptr);
16323 1695 }
16324
16325 50115 int ha_innobase::truncate_impl(const char *name, TABLE *form,
16326 dd::Table *table_def) {
16327
1/2
✓ Branch 0 taken 50115 times.
✗ Branch 1 not taken.
50115 DBUG_TRACE;
16328
16329 /* Truncate of intrinsic table or hard-coded DD tables is not allowed
16330 for now. */
16331
2/4
✓ Branch 0 taken 50115 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50115 times.
100230 if (table_def == nullptr ||
16332
3/6
✓ Branch 0 taken 50115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50115 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 50115 times.
50115 dict_sys_t::is_dd_table_id(table_def->se_private_id())) {
16333 my_error(ER_NOT_ALLOWED_COMMAND, MYF(0));
16334 return HA_ERR_UNSUPPORTED;
16335 }
16336
16337
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 50111 times.
50115 if (high_level_read_only) {
16338 4 return HA_ERR_TABLE_READONLY;
16339 }
16340
16341 char norm_name[FN_REFLEN];
16342
1/2
✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
50111 THD *thd = ha_thd();
16343 50111 dict_table_t *innodb_table = nullptr;
16344 50111 bool has_autoinc = false;
16345 50111 int error = 0;
16346
1/2
✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
50111 const bool is_instant = dd_table_has_instant_cols(*table_def);
16347
16348
2/4
✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50111 times.
50111 if (!normalize_table_name(norm_name, name)) {
16349 /* purecov: begin inspected */
16350 ut_d(ut_error);
16351 ut_o(return (HA_ERR_TOO_LONG_PATH));
16352 /* purecov: end */
16353 }
16354
16355 innobase_truncate<dd::Table> truncator(thd, norm_name, form, table_def, false,
16356
1/2
✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
50111 true);
16357
16358
1/2
✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
50111 error = truncator.open_table(innodb_table);
16359
16360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50111 times.
50111 if (error != 0) {
16361 return error;
16362 }
16363
16364 50111 has_autoinc = dict_table_has_autoinc_col(innodb_table);
16365
16366
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50109 times.
50111 if (dict_table_is_discarded(innodb_table)) {
16367
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, norm_name);
16368 2 return HA_ERR_NO_SUCH_TABLE;
16369
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50107 times.
50109 } else if (innodb_table->ibd_file_missing) {
16370 2 return innodb_table->keyring_encryption_info.page0_has_crypt_data == true
16371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ? HA_ERR_ENCRYPTION_KEY_MISSING
16372 2 : HA_ERR_TABLESPACE_MISSING;
16373 }
16374
16375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50107 times.
50107 if (UNIV_UNLIKELY(innodb_table->is_corrupt)) return HA_ERR_CRASHED;
16376
16377
1/2
✓ Branch 0 taken 50107 times.
✗ Branch 1 not taken.
50107 trx_t *trx = check_trx_exists(thd);
16378
1/2
✓ Branch 0 taken 50107 times.
✗ Branch 1 not taken.
50107 innobase_register_trx(ht, thd, trx);
16379
16380
1/2
✓ Branch 0 taken 50091 times.
✗ Branch 1 not taken.
50107 error = truncator.exec();
16381
16382
2/2
✓ Branch 0 taken 50086 times.
✓ Branch 1 taken 5 times.
50091 if (error == 0) {
16383
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 49717 times.
50086 if (has_autoinc) {
16384
2/4
✓ Branch 0 taken 369 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 369 times.
✗ Branch 3 not taken.
369 dd_set_autoinc(table_def->se_private_data(), 0);
16385 }
16386
16387
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 50078 times.
50086 if (is_instant) {
16388
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (dd_clear_instant_table(*table_def, true) != DB_SUCCESS) {
16389 error = HA_ERR_GENERIC;
16390 }
16391 }
16392 }
16393
16394 50091 return error;
16395 50099 }
16396
16397 /** Drop a table.
16398 @param[in] name table name
16399 @param[in] table_def dd::Table describing table to
16400 be dropped
16401 @return error number
16402 @retval 0 on success */
16403 328139 int ha_innobase::delete_table(const char *name, const dd::Table *table_def) {
16404
4/4
✓ Branch 0 taken 145496 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 328137 times.
473635 if (table_def != nullptr &&
16405
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 145494 times.
145496 dict_sys_t::is_dd_table_id(table_def->se_private_id())) {
16406 2 my_error(ER_NOT_ALLOWED_COMMAND, MYF(0));
16407 2 return (HA_ERR_UNSUPPORTED);
16408 }
16409
16410 328137 THD *thd = ha_thd();
16411 328137 trx_t *trx = check_trx_exists(thd);
16412
16413
6/6
✓ Branch 0 taken 145494 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 99389 times.
✓ Branch 3 taken 46105 times.
✓ Branch 4 taken 99389 times.
✓ Branch 5 taken 228748 times.
328137 if (table_def != nullptr && table_def->is_persistent()) {
16414 99389 innobase_register_trx(ht, thd, trx);
16415 }
16416
16417 328137 return (innobase_basic_ddl::delete_impl(thd, name, table_def, nullptr));
16418 }
16419
16420 /** Validate the parameters in st_alter_tablespace
16421 before using them in InnoDB tablespace functions.
16422 @param[in] type Type os tablespace being validated
16423 @param[in] alter_info How to do the command.
16424 @return MySQL handler error code like HA_... */
16425 1350 static int validate_create_tablespace_info(ib_file_suffix type,
16426 st_alter_tablespace *alter_info) {
16427 /* The parser ensures that these fields are provided. */
16428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
1350 ut_a(alter_info->data_file_name != nullptr);
16429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
1350 ut_a(alter_info->tablespace_name != nullptr);
16430
16431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
1350 if (high_level_read_only) {
16432 return (HA_ERR_INNODB_READ_ONLY);
16433 }
16434
16435 /* Name validation should be ensured from the SQL layer. */
16436
2/4
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1350 times.
1350 ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type,
16437 alter_info->tablespace_name));
16438
16439 1350 int error = 0;
16440
16441 /* Make sure the tablespace is not already open. */
16442
16443 space_id_t space_id;
16444
16445
1/2
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
1350 space_id = fil_space_get_id_by_name(alter_info->tablespace_name);
16446
16447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
1350 if (space_id != SPACE_UNKNOWN) {
16448 my_printf_error(ER_TABLESPACE_EXISTS,
16449 "InnoDB: A tablespace named `%s`"
16450 " already exists.",
16451 MYF(0), alter_info->tablespace_name);
16452 error = HA_ERR_TABLESPACE_EXISTS;
16453 }
16454
16455
4/4
✓ Branch 0 taken 974 times.
✓ Branch 1 taken 376 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 919 times.
1350 if (type == IBD && alter_info->file_block_size) {
16456 /* Check for a bad file block size. */
16457
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2 times.
55 if (!ut_is_2pow(alter_info->file_block_size) ||
16458
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
53 alter_info->file_block_size < UNIV_ZIP_SIZE_MIN ||
16459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 alter_info->file_block_size > UNIV_PAGE_SIZE_MAX) {
16460
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
16461 "InnoDB does not support"
16462 " FILE_BLOCK_SIZE=%llu",
16463 MYF(0), alter_info->file_block_size);
16464 2 error = HA_WRONG_CREATE_OPTION;
16465
16466 /* Don't allow a file block size larger than UNIV_PAGE_SIZE. */
16467
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 41 times.
53 } else if (alter_info->file_block_size > UNIV_PAGE_SIZE) {
16468
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
16469 "InnoDB: Cannot create a tablespace"
16470 " with FILE_BLOCK_SIZE=%llu because"
16471 " INNODB_PAGE_SIZE=%lu.",
16472 MYF(0), alter_info->file_block_size, UNIV_PAGE_SIZE);
16473 12 error = HA_WRONG_CREATE_OPTION;
16474
16475 /* Don't allow a compressed tablespace when page size > 16k. */
16476
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 28 times.
41 } else if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF &&
16477
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
13 alter_info->file_block_size != UNIV_PAGE_SIZE) {
16478
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION,
16479 "InnoDB: Cannot create a COMPRESSED"
16480 " tablespace when innodb_page_size >"
16481 " 16k.",
16482 MYF(0));
16483 11 error = HA_WRONG_CREATE_OPTION;
16484 }
16485 }
16486
16487 /* Validate AUTOEXTEND_SIZE clause. */
16488 1350 if (alter_info->autoextend_size.has_value() &&
16489
6/8
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1311 times.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 1346 times.
1389 alter_info->autoextend_size.value() > 0 &&
16490
4/6
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 35 times.
39 validate_autoextend_size_value(alter_info->autoextend_size.value()) !=
16491 DB_SUCCESS) {
16492 4 error = HA_WRONG_CREATE_OPTION;
16493 }
16494
16495 /* Validate the ADD DATAFILE name. */
16496
1/2
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
1350 std::string datafile_name(alter_info->data_file_name);
16497
16498 /* Undo Tablespace ADD DATAFILE filenames cannot be relative paths
16499 because it would be unclear what they are relative to. However,
16500 srv_undo_dir can be a relative directory. So evaluate this
16501 ADD DATAFILE value before it is appended to the undo dir. */
16502
7/8
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 974 times.
✓ Branch 2 taken 376 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 369 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1343 times.
1350 if (type == IBU && Fil_path::is_relative_path(datafile_name)) {
16503
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(ER_WRONG_FILE_NAME,
16504 "The ADD DATAFILE filepath for an UNDO TABLESPACE"
16505 " cannot be a relative path.",
16506 MYF(0));
16507
16508 7 error = HA_ERR_WRONG_FILE_NAME;
16509 }
16510
16511 /* If this is an undo tablespace basename and the innodb-undo-directory
16512 is not the datadir, then use an undo::Tablespace object to get the name
16513 since it will to attach a basename to the undo directory instead of the
16514 datadir. */
16515
2/2
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 18 times.
376 if (alter_info->ts_cmd_type == CREATE_UNDO_TABLESPACE &&
16516
4/4
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 974 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1348 times.
1726 std::string::npos == datafile_name.find_first_of(Fil_path::SEPARATOR) &&
16517
3/4
✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 356 times.
358 !MySQL_undo_path.is_same_as(MySQL_datadir_path)) {
16518 2 undo::Tablespace undo_space(0);
16519
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 undo_space.set_file_name(datafile_name.c_str());
16520
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 datafile_name = undo_space.file_name();
16521 2 }
16522
16523
1/2
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
1350 Fil_path filepath(datafile_name, true);
16524
16525 /* If this path contains a circular section such as "/anydir/../" then
16526 reject it since if that unnecessary directory reference is deleted
16527 the path will not be useaable on Linux. */
16528
3/4
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1341 times.
1350 if (filepath.is_circular()) {
16529
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_printf_error(ER_WRONG_FILE_NAME,
16530 "The ADD DATAFILE filepath cannot contain circular "
16531 "directory references.",
16532 MYF(0));
16533 9 error = HA_ERR_WRONG_FILE_NAME;
16534 }
16535
16536 #ifndef _WIN32
16537 /* On Non-Windows platforms, '\\' is a valid file name character.
16538 But for InnoDB datafiles, we always assume it is a directory
16539 separator and convert these to '/' */
16540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
1350 if (strchr(filepath, '\\') != nullptr) {
16541 ib::warn(ER_IB_MSG_568) << "Converting backslash to forward slash in"
16542 " ADD DATAFILE "
16543 << filepath.path();
16544 }
16545 #endif /* _WIN32 */
16546
16547 /* The filepath must end with a valid suffix and contain a basename of at
16548 least 1 character before the suffix. */
16549
1/2
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
1350 size_t dirname_len = dirname_length(filepath);
16550 1350 const char *basename = filepath + dirname_len;
16551 1350 auto basename_len = strlen(basename);
16552
16553
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1343 times.
1350 if (basename_len <= 4) {
16554
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(
16555 ER_WRONG_FILE_NAME,
16556 "The ADD DATAFILE filepath does not have a proper filename.", MYF(0));
16557 7 error = HA_ERR_WRONG_FILE_NAME;
16558 }
16559
16560
4/6
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1350 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1344 times.
1350 if (!Fil_path::has_suffix(type, basename)) {
16561 6 my_printf_error(ER_WRONG_FILE_NAME,
16562 "The ADD DATAFILE filepath must end with '%s'.", MYF(0),
16563
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 dot_ext[type]);
16564 6 error = HA_ERR_WRONG_FILE_NAME;
16565 }
16566
16567
3/4
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1348 times.
1350 if (!filepath.is_valid()) {
16568
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_FILE_NAME, MYF(0), filepath.path().c_str());
16569
16570
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_WRONG_FILE_NAME, "Invalid use of ':'.", MYF(0));
16571
16572 2 return (HA_ERR_WRONG_FILE_NAME);
16573 }
16574
16575 /* If this file already exists, we cannot use this filename. */
16576
3/4
✓ Branch 0 taken 1348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1344 times.
1348 if (os_file_exists(filepath.path().c_str())) {
16577
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_printf_error(ER_WRONG_FILE_NAME,
16578 "The ADD DATAFILE filepath already exists.", MYF(0));
16579 4 error = HA_ERR_WRONG_FILE_NAME;
16580 }
16581
16582 78 Fil_path dirpath((dirname_len == 0 ? "." : datafile_name.c_str()),
16583
5/6
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1270 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 1270 times.
✓ Branch 4 taken 1348 times.
✗ Branch 5 not taken.
1426 (dirname_len == 0 ? 1 : dirname_len), true);
16584
16585
3/4
✓ Branch 0 taken 1348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1342 times.
1348 if (!dirpath.is_directory_and_exists()) {
16586
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 ib::error(ER_IB_MSG_WRONG_TABLESPACE_DIR, alter_info->tablespace_name);
16587
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_printf_error(ER_WRONG_FILE_NAME,
16588 "The directory does not exist or is incorrect.", MYF(0));
16589
16590 6 error = HA_ERR_WRONG_FILE_NAME;
16591 }
16592
16593 /* Do not allow the file to be created in a unique undo directory. */
16594
6/6
✓ Branch 0 taken 972 times.
✓ Branch 1 taken 376 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 966 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1347 times.
1354 if (type == IBD && MySQL_undo_path_is_unique &&
16595
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
6 (MySQL_undo_path.is_same_as(dirpath) ||
16596
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 MySQL_undo_path.is_ancestor(dirpath))) {
16597
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 std::string msg("The DATAFILE location cannot be the undo directory.");
16598
16599
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
16600
16601 1 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE,
16602
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 alter_info->tablespace_name, msg.c_str());
16603
16604 1 error = HA_ERR_WRONG_FILE_NAME;
16605 1 }
16606
16607 /* General tablespaces can be inside but not under the datadir
16608 since those directories contain datafiles for specific schemas.*/
16609
7/8
✓ Branch 0 taken 972 times.
✓ Branch 1 taken 376 times.
✓ Branch 2 taken 972 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 965 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1341 times.
1348 if (type == IBD && MySQL_datadir_path.is_ancestor(dirpath)) {
16610
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 std::string msg("The DATAFILE location cannot be under the datadir.");
16611
16612
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
16613
16614 7 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE,
16615
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 alter_info->tablespace_name, msg.c_str());
16616
16617 7 error = HA_ERR_WRONG_FILE_NAME;
16618 7 }
16619
16620 /* Validate the tablespace location. */
16621
3/4
✓ Branch 0 taken 1348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1341 times.
✓ Branch 3 taken 7 times.
2689 bool in_datadir = MySQL_datadir_path.is_ancestor(dirpath) ||
16622
3/4
✓ Branch 0 taken 1341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1291 times.
✓ Branch 3 taken 50 times.
1341 MySQL_datadir_path.is_same_as(dirpath);
16623 bool in_known_location =
16624
3/4
✓ Branch 0 taken 1298 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
1348 in_datadir ? true : fil_path_is_known(dirpath.path());
16625
16626 /* All undo and general tablespaces must be in known directories */
16627
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1328 times.
1348 if (!in_known_location) {
16628
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 std::string msg("The ");
16629
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 msg += (type == IBU ? "UNDO " : "");
16630
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 msg += "DATAFILE location must be in a known directory.";
16631
16632
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str());
16633
16634 20 ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE,
16635
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 alter_info->tablespace_name, msg.c_str());
16636
16637 20 error = HA_ERR_WRONG_FILE_NAME;
16638 20 }
16639
16640 1348 return (error);
16641 1350 }
16642
16643 /** CREATE a tablespace.
16644 @param[in] hton Handlerton of InnoDB
16645 @param[in] thd Connection
16646 @param[in] alter_info How to do the command
16647 @param[in,out] dd_space Tablespace metadata
16648 @return MySQL error code*/
16649 974 static int innodb_create_tablespace(handlerton *hton, THD *thd,
16650 st_alter_tablespace *alter_info,
16651 dd::Tablespace *dd_space) {
16652 int error;
16653
1/2
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
974 Tablespace tablespace;
16654 974 uint32_t fsp_flags = 0;
16655 974 fil_encryption_t keyring_encryption_mode{FIL_ENCRYPTION_DEFAULT};
16656
16657
1/2
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
974 DBUG_TRACE;
16658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 974 times.
974 assert(hton == innodb_hton_ptr);
16659
16660
2/4
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 974 times.
974 ut_ad(alter_info->tablespace_name == dd_space->name());
16661
2/4
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 974 times.
974 ut_ad(strcmp(alter_info->data_file_name,
16662 dd_tablespace_get_filename(dd_space)) == 0);
16663
16664 /* Be sure the input parameters are valid before continuing. */
16665
1/2
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
974 error = validate_create_tablespace_info(IBD, alter_info);
16666
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 912 times.
974 if (error) {
16667 62 return error;
16668 }
16669
16670 /* Create the tablespace object. */
16671
1/2
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
912 tablespace.set_name(alter_info->tablespace_name);
16672
16673
1/2
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
912 dberr_t err = tablespace.add_datafile(alter_info->data_file_name);
16674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 912 times.
912 if (err != DB_SUCCESS) {
16675 return convert_error_code_to_mysql(err, 0, nullptr);
16676 }
16677
16678
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 877 times.
947 tablespace.set_autoextend_size(alter_info->autoextend_size.has_value()
16679
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 ? alter_info->autoextend_size.value()
16680 : 0);
16681
16682 /* Get the transaction associated with the current thd. */
16683
1/2
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
912 trx_t *trx = check_trx_exists(thd);
16684
1/2
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
912 TrxInInnoDB trx_in_innodb(trx);
16685
1/2
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
912 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
16686 912 ++trx->will_lock;
16687
16688
1/2
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
912 row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE);
16689
16690 /* In FSP_FLAGS, a zip_ssize of zero means that the tablespace
16691 holds non-compresssed tables. A non-zero zip_ssize means that
16692 the general tablespace can ONLY contain compressed tables. */
16693 912 uint32_t zip_size = static_cast<uint32_t>(alter_info->file_block_size);
16694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 912 times.
912 ut_ad(zip_size <= UNIV_PAGE_SIZE_MAX);
16695
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 30 times.
912 if (zip_size == 0) {
16696 882 zip_size = UNIV_PAGE_SIZE;
16697 }
16698 912 bool zipped = (zip_size != UNIV_PAGE_SIZE);
16699
1/2
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
912 page_size_t page_size(zip_size, UNIV_PAGE_SIZE, zipped);
16700 912 bool atomic_blobs = page_size.is_compressed();
16701 912 KeyringEncryptionKeyIdInfo keyring_encryption_key_id;
16702 912 bool encrypted = false;
16703 912 dd::String_type encrypt;
16704
4/8
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 912 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 912 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 912 times.
✗ Branch 7 not taken.
912 if (dd_space->options().exists("encryption")) {
16705
3/6
✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 912 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 912 times.
✗ Branch 5 not taken.
912 (void)dd_space->options().get("encryption", &encrypt);
16706
16707 /* Validate Encryption option provided */
16708
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 892 times.
912 if (Encryption::validate_for_tablespace(encrypt.c_str()) != DB_SUCCESS) {
16709 /* Incorrect encryption option */
16710
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
16711 20 err = DB_UNSUPPORTED;
16712 22 goto error_exit;
16713 }
16714
16715 892 bool explicit_encryption{false};
16716
4/8
✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 892 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 892 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 892 times.
✗ Branch 7 not taken.
892 if (dd_space->options().exists("explicit_encryption")) {
16717
3/6
✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 892 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 892 times.
✗ Branch 5 not taken.
892 (void)dd_space->options().get("explicit_encryption",
16718 &explicit_encryption);
16719 }
16720 /* Validate that encryption is not MK encryption if online encryption is ON.
16721 encrypt_type is set to Y for both MK encryption and ONLINE_TO_KEYRING
16722 encryption. However, when d_t_e=ONLINE_TO_KEYRING is set it is only
16723 possible to specify MK encryption by explicitly specifying
16724 ENCRYPTION='Y'. We use this information here.
16725 */
16726
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 24 times.
1188 if (Encryption::is_master_key_encryption(encrypt.c_str()) &&
16727
4/6
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 596 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 892 times.
1188 explicit_encryption && Encryption::is_online_encryption_on()) {
16728 my_printf_error(
16729 ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION,
16730 "InnoDB: ENCRYPTED='Y' not supported for tablespace because "
16731 "online encryption to KEYRING is turned ON.",
16732 MYF(0));
16733 err = DB_UNSUPPORTED;
16734 goto error_exit;
16735 }
16736
16737 /* If encryption is to be done */
16738
2/2
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 596 times.
892 if (!Encryption::is_none(encrypt.c_str())) {
16739 /* Check if keyring is ready. */
16740
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 294 times.
296 if (!Encryption::check_keyring()) {
16741
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
16742 2 err = DB_UNSUPPORTED;
16743 2 goto error_exit;
16744 }
16745 294 encrypted = true;
16746 }
16747
16748
4/6
✓ Branch 0 taken 890 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 888 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
890 DBUG_EXECUTE_IF("ib_crash_during_create_tablespace_for_encryption",
16749 DBUG_SUICIDE(););
16750 }
16751
16752 /* Create the filespace flags */
16753 888 fsp_flags =
16754
1/2
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
888 fsp_flags_init(page_size, /* page sizes and a flag if compressed */
16755 atomic_blobs, /* needed only for compressed tables */
16756 false, /* This is not a file-per-table tablespace */
16757 true, /* This is a general shared tablespace */
16758 false, /* Temporary General Tablespaces not allowed */
16759 encrypted); /* If tablespace is to be Encrypted */
16760
1/2
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
888 tablespace.set_flags(fsp_flags);
16761
16762 1776 keyring_encryption_key_id = {
16763 888 alter_info->encryption_key_id.was_encryption_key_id_set,
16764 alter_info->encryption_key_id.id};
16765
16766 keyring_encryption_mode =
16767
1/2
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
888 get_encryption_mode(encrypt.c_str(), alter_info->explicit_encryption);
16768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
888 ut_ad(keyring_encryption_mode != FIL_ENCRYPTION_ON);
16769
16770
1/2
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
888 err = dict_build_tablespace(trx, &tablespace, keyring_encryption_mode,
16771 keyring_encryption_key_id);
16772
16773
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 885 times.
888 if (err == DB_SUCCESS) {
16774 /* Update the fil_space_t with autoextend_size value. */
16775
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 fil_set_autoextend_size(tablespace.space_id(),
16776 tablespace.get_autoextend_size());
16777
16778
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 err = btr_sdi_create_index(tablespace.space_id(), true);
16779
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 if (err == DB_SUCCESS) {
16780 885 fsp_flags_set_sdi(fsp_flags);
16781
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 tablespace.set_flags(fsp_flags);
16782
16783 /* Make sure the DD has the space_id and the flags. */
16784
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 dd_write_tablespace(dd_space, tablespace.space_id(), tablespace.flags(),
16785 DD_SPACE_STATE_NORMAL);
16786 }
16787 }
16788
16789 3 error_exit:
16790
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 885 times.
910 if (err != DB_SUCCESS) {
16791
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 error = convert_error_code_to_mysql(err, 0, nullptr);
16792 }
16793
16794
1/2
✓ Branch 0 taken 910 times.
✗ Branch 1 not taken.
910 row_mysql_unlock_data_dictionary(trx);
16795
16796 910 return error;
16797 972 }
16798
16799 /** Alter AUTOEXTEND_SIZE a tablespace.
16800 @param[in] hton Handlerton of InnoDB
16801 @param[in] alter_info How to do the command
16802 @param[in] old_dd_space Tablespace metadata
16803 @return MySQL error code */
16804 5015 static int innobase_alter_autoextend_size_tablespace(
16805 handlerton *hton, st_alter_tablespace *alter_info,
16806 const dd::Tablespace *old_dd_space) {
16807 5015 space_id_t space_id = SPACE_UNKNOWN;
16808
16809
1/2
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
5015 DBUG_TRACE;
16810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
5015 assert(hton == innodb_hton_ptr);
16811
16812
3/6
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5015 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5015 times.
✗ Branch 5 not taken.
5015 DEBUG_SYNC(current_thd, "innodb_alter_autoextend_size_tablespace");
16813
16814
2/4
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
5015 ut_ad(alter_info->tablespace_name == old_dd_space->name());
16815
16816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
5015 if (srv_read_only_mode) {
16817 return HA_ERR_INNODB_READ_ONLY;
16818 }
16819
16820 /* Validate the name */
16821
2/4
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
5015 ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type,
16822 alter_info->tablespace_name));
16823
16824 /* Be sure that this tablespace is known and valid. */
16825
2/6
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
10030 if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
16826
4/8
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5015 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5015 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5015 times.
✗ Branch 7 not taken.
15045 &space_id) ||
16827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
5015 space_id == SPACE_UNKNOWN) {
16828 return HA_ERR_TABLESPACE_MISSING;
16829 }
16830
16831 /* Make sure tablespace is loaded. */
16832
1/2
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
5015 fil_space_t *space = fil_space_acquire(space_id);
16833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
5015 if (space == nullptr) {
16834 return HA_ERR_TABLESPACE_MISSING;
16835 }
16836
2/4
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
5015 ut_ad(fsp_flags_is_valid(space->flags));
16837
16838 /* Validate the autoextend_size value. */
16839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
5015 ut_ad(alter_info->autoextend_size.has_value());
16840
16841
1/2
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
5015 uint64_t autoextend_size = alter_info->autoextend_size.value();
16842
16843
2/2
✓ Branch 0 taken 5006 times.
✓ Branch 1 taken 9 times.
5015 if (autoextend_size > 0) {
16844
1/2
✓ Branch 0 taken 5006 times.
✗ Branch 1 not taken.
5006 int ret = validate_autoextend_size_value(autoextend_size);
16845
16846
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5004 times.
5006 if (ret != DB_SUCCESS) {
16847
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fil_space_release(space);
16848 2 return ret;
16849 }
16850 }
16851
16852
2/4
✓ Branch 0 taken 5013 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5013 times.
✗ Branch 3 not taken.
5013 fil_set_autoextend_size(space_id, alter_info->autoextend_size.value());
16853
16854
1/2
✓ Branch 0 taken 5013 times.
✗ Branch 1 not taken.
5013 fil_space_release(space);
16855
16856 5013 return 0;
16857 5015 }
16858
16859 /**
16860 Return data filename extension for a InnoDB tablespace.
16861 */
16862
16863 128 static const char *innobase_get_tablespace_filename_ext() { return ".ibd"; }
16864
16865 /** Alter Encrypt/Unencrypt a tablespace.
16866 @param[in] hton Handlerton of InnoDB
16867 @param[in] thd Connection
16868 @param[in] alter_info How to do the command
16869 @param[in] old_dd_space Tablespace metadata
16870 @param[in,out] new_dd_space Tablespace metadata
16871 @return MySQL error code*/
16872 495 static int innobase_alter_encrypt_tablespace(handlerton *hton, THD *thd,
16873 st_alter_tablespace *alter_info,
16874 const dd::Tablespace *old_dd_space,
16875 dd::Tablespace *new_dd_space) {
16876 495 trx_t *trx = nullptr;
16877 495 dberr_t err = DB_SUCCESS;
16878 495 int error = 0;
16879 495 space_id_t space_id = SPACE_UNKNOWN;
16880
16881
1/2
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
495 DBUG_TRACE;
16882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 495 times.
495 assert(hton == innodb_hton_ptr);
16883
16884
4/6
✓ Branch 0 taken 469 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 469 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 469 times.
✗ Branch 5 not taken.
495 DEBUG_SYNC(current_thd, "innodb_alter_encrypt_tablespace");
16885
16886
2/4
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 495 times.
495 ut_ad(alter_info->tablespace_name == old_dd_space->name());
16887
16888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 495 times.
495 if (srv_read_only_mode) {
16889 return HA_ERR_INNODB_READ_ONLY;
16890 }
16891
16892 /* Name validation should be ensured from the SQL layer. */
16893
2/4
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 495 times.
495 ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type,
16894 alter_info->tablespace_name));
16895
16896 /* Be sure that this tablespace is known and valid. */
16897
2/6
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 495 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
990 if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
16898
4/8
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 495 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 495 times.
✗ Branch 7 not taken.
1485 &space_id) ||
16899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 495 times.
495 space_id == SPACE_UNKNOWN) {
16900 return HA_ERR_TABLESPACE_MISSING;
16901 }
16902
16903 /* Make sure keyring plugin is loaded. */
16904
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 479 times.
495 if (!Encryption::check_keyring()) {
16905
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0));
16906
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr);
16907 16 return error;
16908 }
16909
16910 /* Make sure tablespace is loaded. */
16911
1/2
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
479 fil_space_t *space = fil_space_get(space_id);
16912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 479 times.
479 if (space == nullptr) {
16913 return HA_ERR_TABLESPACE_MISSING;
16914 }
16915
2/4
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 479 times.
479 ut_ad(fsp_flags_is_valid(space->flags));
16916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 479 times.
479 ut_ad(FSP_FLAGS_GET_SHARED(space->flags));
16917
16918
1/2
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
479 const dd::Properties &oldopts = old_dd_space->options();
16919
1/2
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
479 const dd::Properties &newopts = new_dd_space->options();
16920
16921 /* Get value of old encryption option. */
16922 479 dd::String_type oldenc;
16923
3/6
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 479 times.
✗ Branch 5 not taken.
479 if (oldopts.exists("encryption")) {
16924
2/4
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
479 (void)oldopts.get("encryption", &oldenc);
16925 }
16926
16927 /* Get value of new encryption option. */
16928
3/6
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 479 times.
479 ut_ad(newopts.exists("encryption"));
16929 479 dd::String_type newenc;
16930
2/4
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
479 (void)newopts.get("encryption", &newenc);
16931
16932 /* Validate new encryption option provided */
16933 479 const char *encrypt = newenc.data();
16934
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 433 times.
479 if (Encryption::validate_for_tablespace(encrypt) != DB_SUCCESS) {
16935 /* Incorrect encryption option */
16936
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0));
16937
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr);
16938 46 return error;
16939 }
16940
16941 /* If old tablespace definition says it's encrypted */
16942 bool is_old_encrypted =
16943
3/4
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211 times.
✓ Branch 3 taken 222 times.
433 !(oldenc.empty() || Encryption::is_none(oldenc.data()));
16944 /* If new tablespace definition says it's encrypted */
16945 433 bool is_new_encrypted = !Encryption::is_none(newenc.data());
16946 433 fil_space_crypt_t *crypt_data = space->crypt_data;
16947
16948 433 bool to_encrypt = false;
16949 // It is only possible to mark tablespace to be skipped by encryption threads
16950 // if it is not already encrypted.
16951
4/4
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 211 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 174 times.
433 if (!is_old_encrypted && !is_new_encrypted &&
16952
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 alter_info->explicit_encryption) {
16953
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 if (!fil_crypt_exclude_tablespace_from_rotation_permanently(space)) {
16954 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
16955 }
16956 48 return error;
16957
3/4
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 211 times.
✓ Branch 2 taken 174 times.
✗ Branch 3 not taken.
385 } else if (!is_old_encrypted && is_new_encrypted) {
16958
3/4
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
174 DEBUG_SYNC_C("alter_encryption_to_y");
16959
2/4
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 174 times.
174 if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) {
16960 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
16961 }
16962
3/4
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
174 DEBUG_SYNC_C("alter_encryption_to_y_tablespace_excluded");
16963
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 158 times.
174 if (crypt_data != nullptr) {
16964
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 mutex_enter(&crypt_data->mutex);
16965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 ut_ad(crypt_data->type == CRYPT_SCHEME_UNENCRYPTED);
16966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 ut_ad(crypt_data->min_key_version ==
16967 ENCRYPTION_KEY_VERSION_NOT_ENCRYPTED);
16968 // setting it to default - it could have been FIL_ENCRYPTION_N
16969 // however, now that it gets encrypted with Master Key encryption
16970 // the user will have a chance to re-encrypt it with KEYRING
16971 16 crypt_data->encryption = FIL_ENCRYPTION_DEFAULT;
16972
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 mutex_exit(&space->crypt_data->mutex);
16973 }
16974 /* Encrypt tablespace */
16975 174 to_encrypt = true;
16976
3/4
✓ Branch 0 taken 211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 53 times.
211 } else if (is_old_encrypted && !is_new_encrypted) {
16977
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 146 times.
158 if (crypt_data) {
16978
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mutex_enter(&crypt_data->mutex);
16979 12 bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED};
16980
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mutex_exit(&crypt_data->mutex);
16981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (is_keyring_encrypted) {
16982 my_error(ER_EXPLICIT_DECRYPTION_OF_ONLINE_ENCRYPTED_TABLESPACE, MYF(0),
16983 space->name);
16984 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
16985 }
16986 }
16987
3/4
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
158 DEBUG_SYNC_C("alter_encryption_to_n");
16988 // do not want master key decryption to get into way of encryption threads
16989
2/4
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 158 times.
158 if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) {
16990 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
16991 }
16992
3/4
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
158 DEBUG_SYNC_C("alter_encryption_to_n_tablespace_excluded");
16993 /* Unencrypt tablespace */
16994 158 to_encrypt = false;
16995 158 } else {
16996 // If tablespace is encrypted by encryption threads - it cannot be
16997 // re-encrypted with Master Key encryption. It must first decrypted with
16998 // encryption threads.
16999
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
53 if (space->crypt_data != nullptr && alter_info->explicit_encryption) {
17000
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 mutex_enter(&crypt_data->mutex);
17001 26 bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED};
17002
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 mutex_exit(&crypt_data->mutex);
17003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (is_keyring_encrypted) {
17004 my_error(ER_ONLINE_KEYRING_TO_MK_RE_ENCRYPTION, MYF(0), space->name);
17005 return convert_error_code_to_mysql(DB_ERROR, 0, NULL);
17006 }
17007 }
17008 /* Nothing to do */
17009 53 return error;
17010 }
17011
17012 /* Get the transaction associated with the current thd */
17013
1/2
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
332 trx = check_trx_exists(thd);
17014
1/2
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
332 innobase_register_trx(hton, thd, trx);
17015
17016
1/2
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
332 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
17017
17018
4/6
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 326 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
332 DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_before_processing",
17019 DBUG_SUICIDE(););
17020
17021 /* do encryption/unencryption processing now. */
17022
1/2
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
326 err = fsp_alter_encrypt_tablespace(thd, space_id, to_encrypt, new_dd_space);
17023
17024
4/6
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 239 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
245 DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_after_processing",
17025 DBUG_SUICIDE(););
17026
17027
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 error = convert_error_code_to_mysql(err, 0, nullptr);
17028 239 return error;
17029 402 }
17030
17031 /** ALTER an undo tablespace.
17032 @param[in] hton Handlerton of InnoDB
17033 @param[in] thd Connection
17034 @param[in] alter_info How to do the command
17035 @param[in] old_dd_space Tablespace metadata
17036 @param[in] new_dd_space Tablespace metadata
17037 @return MySQL error code*/
17038 5600 static int innodb_alter_tablespace(handlerton *hton, THD *thd,
17039 st_alter_tablespace *alter_info,
17040 const dd::Tablespace *old_dd_space,
17041 dd::Tablespace *new_dd_space) {
17042 5600 space_id_t space_id = SPACE_UNKNOWN;
17043 ulint old_size, new_size;
17044
17045
1/2
✓ Branch 0 taken 5600 times.
✗ Branch 1 not taken.
5600 DBUG_TRACE;
17046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5600 times.
5600 assert(hton == innodb_hton_ptr);
17047
17048
2/2
✓ Branch 0 taken 5529 times.
✓ Branch 1 taken 71 times.
5600 if (alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_RENAME &&
17049
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5511 times.
5529 alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_OPTIONS) {
17050 18 return HA_ADMIN_NOT_IMPLEMENTED;
17051 }
17052
17053 /* Name validation should be ensured from the SQL layer. */
17054
2/4
✓ Branch 0 taken 5582 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5582 times.
5582 ut_ad(0 == validate_tablespace_name(ALTER_TABLESPACE,
17055 alter_info->tablespace_name));
17056
17057 /* Be sure that this tablespace is known and valid. */
17058
3/6
✓ Branch 0 taken 5582 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5581 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11164 if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
17059 5582 &space_id) ||
17060
8/14
✓ Branch 0 taken 5582 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5582 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5582 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5582 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5582 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 5581 times.
✓ Branch 12 taken 5582 times.
✗ Branch 13 not taken.
11164 space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) {
17061 1 return HA_ERR_TABLESPACE_MISSING;
17062 }
17063
17064
3/4
✓ Branch 0 taken 5581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5580 times.
5581 if (fsp_is_undo_tablespace(space_id)) {
17065
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_TABLESPACE_NAME,
17066 "Cannot ALTER TABLESPACE `%s` because it is an undo "
17067 "tablespace. Please use ALTER UNDO TABLESPACE.",
17068 MYF(0), alter_info->tablespace_name);
17069
17070 1 return HA_ERR_NOT_ALLOWED_COMMAND;
17071 }
17072
17073 /* ALTER_TABLESPACE_OPTIONS */
17074
2/2
✓ Branch 0 taken 5511 times.
✓ Branch 1 taken 69 times.
5580 if (alter_info->ts_alter_tablespace_type == ALTER_TABLESPACE_OPTIONS) {
17075 5511 int err = 0;
17076 /* Process the encryption option if specified with the
17077 ALTER TABLESPACE statement. */
17078
2/2
✓ Branch 0 taken 495 times.
✓ Branch 1 taken 5016 times.
6006 if (alter_info->encryption != nullptr &&
17079
8/14
✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 495 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 495 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 495 times.
✓ Branch 9 taken 5016 times.
✓ Branch 10 taken 495 times.
✓ Branch 11 taken 5016 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
6006 new_dd_space->options().exists("encryption")) {
17080
1/2
✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
495 err = innobase_alter_encrypt_tablespace(hton, thd, alter_info,
17081 old_dd_space, new_dd_space);
17082 }
17083
17084 /* Process the AUTOEXTEND_SIZE clause if mentioned with
17085 the ALTER TABLESPACE statement. */
17086
4/4
✓ Branch 0 taken 5353 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 5015 times.
✓ Branch 3 taken 338 times.
10433 if (!err && alter_info->autoextend_size.has_value() &&
17087
8/14
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5015 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5015 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5015 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5015 times.
✓ Branch 9 taken 403 times.
✓ Branch 10 taken 5015 times.
✓ Branch 11 taken 403 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
10433 new_dd_space->options().exists(autoextend_size_str)) {
17088
1/2
✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
5015 err = innobase_alter_autoextend_size_tablespace(hton, alter_info,
17089 old_dd_space);
17090 }
17091
17092 /* Ignore any other ALTER TABLESPACE options. */
17093 5418 return err;
17094 }
17095
17096 /* ALTER_TABLESPACE_RENAME */
17097
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 const char *from = old_dd_space->name().c_str();
17098
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 const char *to = new_dd_space->name().c_str();
17099
17100 /* mysql tablespace can't be renamed */
17101
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 if (innobase_strcasecmp(from, dict_sys_t::s_dd_space_name) == 0) {
17102 my_printf_error(ER_WRONG_TABLESPACE_NAME,
17103 "InnoDB: `mysql` is a reserved"
17104 " tablespace name.",
17105 MYF(0));
17106 return HA_WRONG_CREATE_OPTION;
17107 }
17108
17109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 ut_ad(ut_strcmp(from, to) != 0);
17110
17111
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 dberr_t err = fil_rename_tablespace_by_id(space_id, from, to);
17112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (err != DB_SUCCESS) {
17113 return convert_error_code_to_mysql(err, 0, nullptr);
17114 }
17115
17116 /* Rename any in-memory cached table->tablespace */
17117
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 dict_sys_mutex_enter();
17118
6/10
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2964 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3033 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2964 times.
✓ Branch 9 taken 69 times.
3033 for (auto table : dict_sys->table_LRU) {
17119
6/6
✓ Branch 0 taken 2822 times.
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 2736 times.
✓ Branch 4 taken 86 times.
✓ Branch 5 taken 2878 times.
2964 if (table->tablespace && strcmp(from, table->tablespace) == 0) {
17120
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 old_size = mem_heap_get_size(table->heap);
17121
17122
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to));
17123
17124
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 new_size = mem_heap_get_size(table->heap);
17125 86 dict_sys->size += new_size - old_size;
17126 }
17127 }
17128
17129
6/10
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1741 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1810 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1741 times.
✓ Branch 9 taken 69 times.
1810 for (auto table : dict_sys->table_non_LRU) {
17130
4/6
✓ Branch 0 taken 1648 times.
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1648 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1741 times.
1741 if (table->tablespace && strcmp(from, table->tablespace) == 0) {
17131 old_size = mem_heap_get_size(table->heap);
17132
17133 table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to));
17134
17135 new_size = mem_heap_get_size(table->heap);
17136 dict_sys->size += new_size - old_size;
17137 }
17138 }
17139
17140
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 dict_sys_mutex_exit();
17141
17142 69 return 0;
17143 5507 }
17144
17145 /** DROP a tablespace.
17146 @param[in] hton Handlerton of InnoDB
17147 @param[in] thd Connection
17148 @param[in] alter_info How to do the command
17149 @param[in] dd_space Tablespace metadata
17150 @return MySQL error code*/
17151 885 static int innodb_drop_tablespace(handlerton *hton, THD *thd,
17152 st_alter_tablespace *alter_info,
17153 const dd::Tablespace *dd_space) {
17154 885 int error = 0;
17155 885 space_id_t space_id = SPACE_UNKNOWN;
17156
17157
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 DBUG_TRACE;
17158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
885 assert(hton == innodb_hton_ptr);
17159
17160
2/4
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 885 times.
✗ Branch 3 not taken.
885 auto dd_space_name = dd_space->name();
17161
17162
2/4
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 885 times.
885 ut_ad(alter_info->tablespace_name == dd_space->name());
17163
17164 /* Name validation should be ensured from the SQL layer. */
17165
2/4
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 885 times.
885 ut_ad(0 ==
17166 validate_tablespace_name(DROP_TABLESPACE, alter_info->tablespace_name));
17167
17168 /* Be sure that this tablespace is known and valid. */
17169
2/6
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 885 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1770 if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
17170
4/8
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 885 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 885 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 885 times.
✗ Branch 7 not taken.
2655 &space_id) ||
17171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
885 space_id == SPACE_UNKNOWN) {
17172 return HA_ERR_TABLESPACE_MISSING;
17173 }
17174
17175
3/4
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 884 times.
885 if (fsp_is_undo_tablespace(space_id)) {
17176
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_TABLESPACE_NAME,
17177 "Cannot DROP TABLESPACE `%s` because it is an undo "
17178 "tablespace. Please use DROP UNDO TABLESPACE.",
17179 MYF(0), alter_info->tablespace_name);
17180
17181 1 return HA_ERR_NOT_ALLOWED_COMMAND;
17182 }
17183
17184
3/4
✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 880 times.
884 if (fil_space_get_flags(space_id) == UINT32_UNDEFINED) {
17185 /* The DD knows about it but the actual tablespace is missing.
17186 Allow it to be dropped from the DD. */
17187 4 return 0;
17188 }
17189
17190 /* Get the transaction associated with the current thd. */
17191
1/2
✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
880 trx_t *trx = check_trx_exists(thd);
17192
1/2
✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
880 TrxInInnoDB trx_in_innodb(trx);
17193
1/2
✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
880 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
17194 880 ++trx->will_lock;
17195
17196 /* Acquire Exclusive MDL on SDI table of tablespace.
17197 This is to prevent concurrent purge on SDI table */
17198 880 MDL_ticket *sdi_mdl = nullptr;
17199
1/2
✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
880 dberr_t err = dd_sdi_acquire_exclusive_mdl(thd, space_id, &sdi_mdl);
17200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 880 times.
880 if (err != DB_SUCCESS) {
17201 error = convert_error_code_to_mysql(err, 0, nullptr);
17202 return error;
17203 }
17204
17205
2/4
✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 880 times.
✗ Branch 3 not taken.
880 err = log_ddl->write_delete_space_log(trx, nullptr, space_id,
17206 dd_tablespace_get_filename(dd_space),
17207 true, false);
17208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 880 times.
880 if (err != DB_SUCCESS) {
17209 error = convert_error_code_to_mysql(err, 0, nullptr);
17210 }
17211
17212 880 return error;
17213 885 }
17214
17215 /** CREATE an undo tablespace.
17216 @param[in] hton Handlerton of InnoDB
17217 @param[in] thd Connection
17218 @param[in] alter_info How to do the command
17219 @param[in,out] dd_space Tablespace metadata
17220 @return MySQL error code*/
17221 376 static int innodb_create_undo_tablespace(handlerton *hton, THD *thd,
17222 st_alter_tablespace *alter_info,
17223 dd::Tablespace *dd_space) {
17224 376 int error = 0;
17225 dberr_t err;
17226 uint32_t flags;
17227
17228
1/2
✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
376 DBUG_TRACE;
17229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
376 assert(hton == innodb_hton_ptr);
17230
17231
2/4
✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 376 times.
376 ut_ad(alter_info->tablespace_name == dd_space->name());
17232
2/4
✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 376 times.
376 ut_ad(strcmp(alter_info->data_file_name,
17233 dd_tablespace_get_filename(dd_space)) == 0);
17234
17235 /* Be sure the input parameters are valid before continuing. */
17236
1/2
✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
376 error = validate_create_tablespace_info(IBU, alter_info);
17237
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 361 times.
376 if (error) {
17238 15 return error;
17239 }
17240
17241 /* Notify clone about the UNDO DDL and possibly wait. We don't
17242 need similar notification for drop which is recoverable with DDL
17243 log. */
17244 Clone_notify notifier(Clone_notify::Type::SPACE_UNDO_DDL,
17245
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 dict_sys_t::s_invalid_space_id, false);
17246
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 360 times.
361 if (notifier.failed()) {
17247 1 return notifier.get_error();
17248 }
17249
17250 /* Create the tablespace object. */
17251
17252 /* Serialize all undo tablespace DDLs */
17253
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 mutex_enter(&undo::ddl_mutex);
17254
17255 /* Get the transaction associated with the current thd and make
17256 sure it will not block this DDL. */
17257
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 check_trx_exists(thd);
17258
17259 /* Allocate a new transaction for this DDL */
17260
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 trx_t *trx = innobase_trx_allocate(thd);
17261
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
17262 360 ++trx->will_lock;
17263
17264 /* Find the next available undo space number and mark it in-use. */
17265
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 space_id_t space_id = undo::get_next_available_space_num();
17266
5/6
✓ Branch 0 taken 359 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 359 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 359 times.
719 if (space_id == SPACE_UNKNOWN ||
17267 359 undo::spaces->size() == FSP_MAX_UNDO_TABLESPACES) {
17268 /* All available explicit undo tablespaces have been used. */
17269 1 ib::error(ER_IB_MSG_MAX_UNDO_SPACES_REACHED, alter_info->tablespace_name,
17270
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 alter_info->data_file_name, int{FSP_MAX_UNDO_TABLESPACES});
17271 1 error = HA_ERR_TABLESPACE_EXISTS;
17272
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 trx_rollback_for_mysql(trx);
17273 1 goto cleanup;
17274 }
17275
17276
1/2
✓ Branch 0 taken 359 times.
✗ Branch 1 not taken.
359 err = srv_undo_tablespace_create(alter_info->tablespace_name,
17277 alter_info->data_file_name, space_id);
17278
17279
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 357 times.
359 if (err != DB_SUCCESS) {
17280
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 error = convert_error_code_to_mysql(err, 0, nullptr);
17281
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_rollback_for_mysql(trx);
17282 2 goto cleanup;
17283 }
17284
17285
1/2
✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
357 innobase_commit_low(trx);
17286
17287 /* Make sure the DD has the space_id and the flags. */
17288
1/2
✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
357 flags = fsp_flags_init(univ_page_size, false, false, false, false);
17289
1/2
✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
357 dd_write_tablespace(dd_space, space_id, flags, DD_SPACE_STATE_ACTIVE);
17290
17291 /* Mark the undo tablespace 'active' in undo::spaces. */
17292
1/2
✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
357 undo::set_active(space_id);
17293
1/2
✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
357 ut_d(ib::info(ER_IB_MSG_UNDO_MARKED_ACTIVE, alter_info->tablespace_name));
17294
17295 360 cleanup:
17296
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 trx_free_for_mysql(trx);
17297
17298
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 mutex_exit(&undo::ddl_mutex);
17299
17300
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 ib::info(ER_IB_MSG_CREATED_UNDO_SPACE, alter_info->tablespace_name);
17301
17302 360 return error;
17303 376 }
17304
17305 /** ALTER an undo tablespace to ACTIVE.
17306 @param[in] undo_space Undo Tablespace object
17307 @param[in] dd_state Current state in the DD.
17308 @param[in] dd_space Tablespace metadata
17309 @return MySQL error code*/
17310 213 static int innodb_alter_undo_tablespace_active(undo::Tablespace *undo_space,
17311 dd::String_type dd_state,
17312 dd::Tablespace *dd_space) {
17313 /* Change the state of the undo tablespace.
17314 ALTER UNDO TABLESPACE is idempotent. */
17315
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 4 times.
213 if (dd_state != dd_space_state_values[DD_SPACE_STATE_ACTIVE]) {
17316 209 dd_tablespace_set_state(dd_space, DD_SPACE_STATE_ACTIVE);
17317 }
17318
17319 /* Start using this undo tablespace. */
17320 213 undo_space->alter_active();
17321
17322 213 return (0);
17323 }
17324
17325 /** ALTER an undo tablespace to INACTIVE.
17326 @param[in] undo_space Undo Tablespace object
17327 @param[in] dd_state Current state in the DD.
17328 @param[in] dd_space Tablespace metadata
17329 @return MySQL error code*/
17330 574 static int innodb_alter_undo_tablespace_inactive(undo::Tablespace *undo_space,
17331 dd::String_type dd_state,
17332 dd::Tablespace *dd_space) {
17333 /* If it is already empty, just return. */
17334
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 571 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 571 times.
577 if (undo_space->is_empty() &&
17335 3 dd_state == dd_space_state_values[DD_SPACE_STATE_EMPTY]) {
17336 3 return (0);
17337 }
17338
17339
2/2
✓ Branch 0 taken 538 times.
✓ Branch 1 taken 33 times.
571 if (undo_space->is_active()) {
17340 /* There must be at least 2 active undo tablespaces besides the one we
17341 are trying to make inactive explicitly. One of those two could be in
17342 the process of being implicitly truncated. So if one other space is
17343 inactive_implicit, then it is being truncated and will be put back
17344 to active before this undo_space is truncated. */
17345 538 ulint other_active_spaces = 0;
17346
2/2
✓ Branch 0 taken 18784 times.
✓ Branch 1 taken 538 times.
19322 for (auto undo_ts : undo::spaces->m_spaces) {
17347
2/2
✓ Branch 0 taken 18246 times.
✓ Branch 1 taken 538 times.
18784 if (undo_ts != undo_space) {
17348
3/4
✓ Branch 0 taken 18246 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9636 times.
✓ Branch 3 taken 8610 times.
18246 if (undo_ts->is_active()) {
17349 9636 other_active_spaces++;
17350
5/6
✓ Branch 0 taken 8610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 8593 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 8593 times.
8627 } else if (undo_ts->is_inactive_implicit() &&
17351 17 purge_sys->undo_trunc.get_marked_space_num() ==
17352
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 undo_ts->num()) {
17353 17 other_active_spaces++;
17354 }
17355 }
17356 }
17357
17358
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 524 times.
538 if (other_active_spaces < 2) {
17359 14 my_printf_error(ER_DISALLOWED_OPERATION,
17360 "Cannot set %s inactive since there would be"
17361 " less than 2 undo tablespaces left active.",
17362 MYF(0), undo_space->space_name());
17363
17364 14 return (HA_ERR_NOT_ALLOWED_COMMAND);
17365 }
17366 }
17367
17368 /* If truncation is happening too often on this undo tablespace there
17369 may be too many old files still in the fil_system with their pages
17370 still in the buffer pool. If this is the case, return an error. */
17371 557 auto count = fil_count_undo_deleted(undo_space->num());
17372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 557 times.
557 if (count > CONCURRENT_UNDO_TRUNCATE_LIMIT) {
17373 my_printf_error(ER_DISALLOWED_OPERATION,
17374 "Cannot set %s inactive since there would be more"
17375 " than %zu old versions of this undo tablespace"
17376 " in cache. Please wait for the next checkpoint.",
17377 MYF(0), undo_space->space_name(),
17378 CONCURRENT_UNDO_TRUNCATE_LIMIT);
17379
17380 return (HA_ERR_NOT_ALLOWED_COMMAND);
17381 }
17382
17383 /* Make sure the DD shows inactive if it is active. */
17384 557 dd_tablespace_set_state(dd_space, DD_SPACE_STATE_INACTIVE);
17385
17386 /* Apply this to new transactions. */
17387 557 undo_space->set_inactive_explicit();
17388
1/2
✓ Branch 0 taken 557 times.
✗ Branch 1 not taken.
557 ut_d(ib::info(ER_IB_MSG_UNDO_ALTERED_INACTIVE, undo_space->file_name()));
17389
17390 557 srv_wake_purge_thread_if_not_active();
17391
17392 557 return (0);
17393 }
17394
17395 /** ALTER an undo tablespace. Either make it ACTIVE or INACTIVE.
17396 @param[in] hton Handlerton of InnoDB
17397 @param[in] alter_info How to do the command
17398 @param[in] dd_space Tablespace metadata
17399 @return MySQL error code*/
17400 789 static int innodb_alter_undo_tablespace(handlerton *hton,
17401 st_alter_tablespace *alter_info,
17402 dd::Tablespace *dd_space) {
17403 789 space_id_t space_id = SPACE_UNKNOWN;
17404
17405
1/2
✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
789 DBUG_TRACE;
17406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 789 times.
789 assert(hton == innodb_hton_ptr);
17407
17408
2/4
✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 789 times.
789 ut_ad(alter_info->tablespace_name == dd_space->name());
17409
17410 /* Name validation should be ensured from the SQL layer. */
17411
2/4
✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 789 times.
789 ut_ad(0 == validate_tablespace_name(ALTER_UNDO_TABLESPACE,
17412 alter_info->tablespace_name));
17413
17414 /* Be sure that this tablespace is known and valid. */
17415
2/6
✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 789 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1578 if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
17416 789 &space_id) ||
17417
7/14
✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 789 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 789 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 789 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 789 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 789 times.
✓ Branch 12 taken 789 times.
✗ Branch 13 not taken.
1578 space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) {
17418 return HA_ERR_TABLESPACE_MISSING;
17419 }
17420
17421
3/4
✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 787 times.
789 if (!fsp_is_undo_tablespace(space_id)) {
17422
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_printf_error(ER_WRONG_TABLESPACE_NAME,
17423 "Cannot ALTER UNDO TABLESPACE `%s` because it is a "
17424 "general tablespace. Please use ALTER TABLESPACE.",
17425 MYF(0), alter_info->tablespace_name);
17426
17427 2 return HA_ERR_NOT_ALLOWED_COMMAND;
17428 }
17429
17430 /* Get the current state of the undo tablespace from the DD. */
17431 787 dd::String_type dd_state;
17432
1/2
✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
787 dd_tablespace_get_state(dd_space, &dd_state, space_id);
17433
17434 /* Serialize all undo tablespace DDLs */
17435
1/2
✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
787 mutex_enter(&undo::ddl_mutex);
17436
17437 /* Get the current undo_space object. */
17438
1/2
✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
787 undo::spaces->s_lock();
17439 787 space_id_t space_num = undo::id2num(space_id);
17440
1/2
✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
787 undo::Tablespace *undo_space = undo::spaces->find(space_num);
17441
17442 /* ALTER UNDO TABLESPACE is idempotent. */
17443 787 int err = 0;
17444
2/3
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 574 times.
✗ Branch 2 not taken.
787 switch (alter_info->ts_alter_tablespace_type) {
17445 213 case ALTER_UNDO_TABLESPACE_SET_ACTIVE:
17446
2/4
✓ Branch 0 taken 213 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
✗ Branch 3 not taken.
213 err = innodb_alter_undo_tablespace_active(undo_space, dd_state, dd_space);
17447 213 break;
17448
17449 574 case ALTER_UNDO_TABLESPACE_SET_INACTIVE:
17450 err =
17451
2/4
✓ Branch 0 taken 574 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 574 times.
✗ Branch 3 not taken.
574 innodb_alter_undo_tablespace_inactive(undo_space, dd_state, dd_space);
17452 574 break;
17453
17454 default:
17455 err = HA_ADMIN_NOT_IMPLEMENTED;
17456 }
17457
17458
1/2
✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
787 undo::spaces->s_unlock();
17459
17460
1/2
✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
787 mutex_exit(&undo::ddl_mutex);
17461
17462 787 return err;
17463 789 }
17464
17465 /** DROP an undo tablespace.
17466 @param[in] hton Handlerton of InnoDB
17467 @param[in] thd Connection
17468 @param[in] alter_info How to do the command
17469 @param[in] dd_space Tablespace metadata
17470 @return MySQL error code*/
17471 342 static int innodb_drop_undo_tablespace(handlerton *hton, THD *thd,
17472 st_alter_tablespace *alter_info,
17473 const dd::Tablespace *dd_space) {
17474 342 space_id_t space_id = SPACE_UNKNOWN;
17475
17476
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 DBUG_TRACE;
17477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 342 times.
342 assert(hton == innodb_hton_ptr);
17478
17479
2/4
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 342 times.
342 ut_ad(alter_info->tablespace_name == dd_space->name());
17480
17481 /* Name validation should be ensured from the SQL layer. */
17482
2/4
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 342 times.
342 ut_ad(0 == validate_tablespace_name(DROP_UNDO_TABLESPACE,
17483 alter_info->tablespace_name));
17484
17485 /* Be sure that this tablespace is known and valid. */
17486
2/6
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 342 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
684 if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID],
17487
4/8
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 342 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 342 times.
✗ Branch 7 not taken.
1026 &space_id) ||
17488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 342 times.
342 space_id == SPACE_UNKNOWN) {
17489 return HA_ERR_TABLESPACE_MISSING;
17490 }
17491
17492
3/4
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 341 times.
342 if (!fsp_is_undo_tablespace(space_id)) {
17493
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_WRONG_TABLESPACE_NAME,
17494 "Cannot DROP UNDO TABLESPACE `%s` because it is a "
17495 "general tablespace. Please use DROP TABLESPACE.",
17496 MYF(0), alter_info->tablespace_name);
17497
17498 1 return HA_ERR_NOT_ALLOWED_COMMAND;
17499 }
17500
17501 /* Serialize all undo tablespace DDLs */
17502
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 mutex_enter(&undo::ddl_mutex);
17503
17504
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 undo::spaces->x_lock();
17505 341 space_id_t space_num = undo::id2num(space_id);
17506
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 undo::Tablespace *undo_space = undo::spaces->find(space_num);
17507
17508 /* If the undo space is missing, allow the DROP UNDO TABLESPACE to
17509 continue to completion. */
17510
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 339 times.
341 if (undo_space == nullptr) {
17511
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 undo::spaces->x_unlock();
17512
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mutex_exit(&undo::ddl_mutex);
17513
17514 /* Start the transaction associated with the current thd so that MySQL
17515 can continue. */
17516
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_t *trx = check_trx_exists(thd);
17517
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
17518 2 ++trx->will_lock;
17519
17520 2 return (0);
17521 }
17522
17523 /* Verify that the undo tablespace is not one of the first two undo spaces,
17524 has been altered inactive and is now empty. */
17525
4/6
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 335 times.
678 if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES ||
17526
3/4
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 335 times.
339 !undo_space->is_empty()) {
17527
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 ib::error err_msg;
17528
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 err_msg << "Cannot drop undo tablespace '" << undo_space->space_name();
17529
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES) {
17530 err_msg << "' because it was not created explicitly.";
17531
3/10
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
4 } else if (undo_space->is_active() || undo_space->is_inactive_implicit()) {
17532
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 err_msg << "' because it is active. "
17533
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
8 << "Please do: ALTER UNDO TABLESPACE " << undo_space->space_name()
17534
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 << " SET INACTIVE;";
17535 } else {
17536 err_msg << "' because it is still being truncated."
17537 " Please try again later.";
17538 }
17539
17540
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 undo::spaces->x_unlock();
17541
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 mutex_exit(&undo::ddl_mutex);
17542
17543 4 return HA_ERR_TABLESPACE_IS_NOT_EMPTY;
17544 4 }
17545
17546 /* We don't need to invalidate buffer pool pages belonging to this undo
17547 tablespace before dropping it, as they will be set as stale and to be
17548 lazily freed. */
17549
17550 /* Save the file name before undo_space is dropped. */
17551
2/4
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 335 times.
✗ Branch 3 not taken.
335 std::string file_name{undo_space->file_name()};
17552
17553 /* Empty and inactive, take it out of view. */
17554
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 undo::spaces->drop(undo_space);
17555
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 undo::spaces->x_unlock();
17556
17557 /* Get the transaction associated with the current thd and write a
17558 delete_space record to the DDL_LOG. */
17559
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 trx_t *trx = check_trx_exists(thd);
17560
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 TrxInInnoDB trx_in_innodb(trx);
17561
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 trx_start_if_not_started(trx, true, UT_LOCATION_HERE);
17562 335 ++trx->will_lock;
17563
17564
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 auto err = log_ddl->write_delete_space_log(trx, nullptr, space_id,
17565 file_name.c_str(), true, false);
17566 335 int error = 0;
17567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
335 if (err != DB_SUCCESS) {
17568 error = convert_error_code_to_mysql(err, 0, nullptr);
17569 }
17570
17571
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 mutex_exit(&undo::ddl_mutex);
17572
17573
1/2
✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
335 ib::info(ER_IB_MSG_DROPPED_UNDO_SPACE, alter_info->tablespace_name);
17574
17575 335 return error;
17576 342 }
17577
17578 /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces.
17579 @param[in] hton Handlerton of InnoDB
17580 @param[in] thd Connection
17581 @param[in] alter_info Describes the command and how to do it.
17582 @param[in] old_ts_def Old version of dd::Tablespace object for the
17583 tablespace.
17584 @param[in,out] new_ts_def New version of dd::Tablespace object for the
17585 tablespace. Can be adjusted by SE. Changes will be persisted in the
17586 data-dictionary at statement commit.
17587 @return MySQL error code*/
17588 8971 static int innobase_alter_tablespace(handlerton *hton, THD *thd,
17589 st_alter_tablespace *alter_info,
17590 const dd::Tablespace *old_ts_def,
17591 dd::Tablespace *new_ts_def) {
17592 8971 int error = 0; /* return zero for success */
17593
1/2
✓ Branch 0 taken 8971 times.
✗ Branch 1 not taken.
8971 DBUG_TRACE;
17594
17595
4/4
✓ Branch 0 taken 8970 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8969 times.
8971 if (srv_read_only_mode || srv_force_recovery > 0) {
17596
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 my_printf_error(ER_INNODB_READ_ONLY,
17597 "Changes to undo tablespaces are not allowed in"
17598 " %s mode",
17599 MYF(0),
17600 (srv_read_only_mode ? "read_only" : "force_recovery"));
17601 2 error = HA_ERR_INNODB_READ_ONLY;
17602 2 goto handle_error;
17603 }
17604
17605
7/7
✓ Branch 0 taken 974 times.
✓ Branch 1 taken 5600 times.
✓ Branch 2 taken 885 times.
✓ Branch 3 taken 376 times.
✓ Branch 4 taken 789 times.
✓ Branch 5 taken 342 times.
✓ Branch 6 taken 3 times.
8969 switch (alter_info->ts_cmd_type) {
17606 974 case CREATE_TABLESPACE:
17607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 974 times.
974 ut_ad(new_ts_def != nullptr);
17608
1/2
✓ Branch 0 taken 972 times.
✗ Branch 1 not taken.
974 error = innodb_create_tablespace(hton, thd, alter_info, new_ts_def);
17609 972 break;
17610
17611 5600 case ALTER_TABLESPACE:
17612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5600 times.
5600 ut_ad(old_ts_def != nullptr);
17613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5600 times.
5600 ut_ad(new_ts_def != nullptr);
17614
1/2
✓ Branch 0 taken 5507 times.
✗ Branch 1 not taken.
5600 error = innodb_alter_tablespace(hton, thd, alter_info, old_ts_def,
17615 new_ts_def);
17616 5507 break;
17617
17618 885 case DROP_TABLESPACE:
17619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
885 ut_ad(old_ts_def != nullptr);
17620
1/2
✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
885 error = innodb_drop_tablespace(hton, thd, alter_info, old_ts_def);
17621 885 break;
17622
17623 376 case CREATE_UNDO_TABLESPACE:
17624
1/2
✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
376 error = innodb_create_undo_tablespace(hton, thd, alter_info, new_ts_def);
17625 376 break;
17626
17627 789 case ALTER_UNDO_TABLESPACE:
17628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 789 times.
789 ut_ad(new_ts_def != nullptr);
17629
1/2
✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
789 error = innodb_alter_undo_tablespace(hton, alter_info, new_ts_def);
17630 789 break;
17631
17632 342 case DROP_UNDO_TABLESPACE:
17633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 342 times.
342 ut_ad(old_ts_def != nullptr);
17634
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 error = innodb_drop_undo_tablespace(hton, thd, alter_info, old_ts_def);
17635 342 break;
17636
17637 3 default:
17638 3 error = HA_ADMIN_NOT_IMPLEMENTED;
17639 }
17640
17641 8876 handle_error:
17642
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 8656 times.
8876 if (error) {
17643 /* These are the most common message params */
17644 220 const char *ibd_type = "TABLESPACE";
17645 220 const char *undo_type = "UNDO TABLESPACE";
17646 220 uint32_t code = ER_CREATE_FILEGROUP_FAILED;
17647 220 const char *subject = ibd_type;
17648
17649 /* Modify those params as needed. */
17650
7/11
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
220 switch (alter_info->ts_cmd_type) {
17651 87 case CREATE_TABLESPACE:
17652 87 break;
17653 87 case ALTER_TABLESPACE:
17654 87 code = ER_ALTER_FILEGROUP_FAILED;
17655 87 break;
17656 2 case DROP_TABLESPACE:
17657 2 code = ER_DROP_FILEGROUP_FAILED;
17658 2 break;
17659 20 case CREATE_UNDO_TABLESPACE:
17660 20 subject = undo_type;
17661 20 break;
17662 16 case ALTER_UNDO_TABLESPACE:
17663 16 code = ER_ALTER_FILEGROUP_FAILED;
17664 16 subject = undo_type;
17665 16 break;
17666 5 case DROP_UNDO_TABLESPACE:
17667 5 code = ER_DROP_FILEGROUP_FAILED;
17668 5 subject = undo_type;
17669 5 break;
17670 3 case CREATE_LOGFILE_GROUP:
17671 case DROP_LOGFILE_GROUP:
17672 case ALTER_LOGFILE_GROUP:
17673 3 subject = "LOGFILE GROUP";
17674 3 break;
17675 case ALTER_ACCESS_MODE_TABLESPACE:
17676 subject = "ACCESS MODE";
17677 break;
17678 case CHANGE_FILE_TABLESPACE:
17679 subject = "CHANGE FILE";
17680 break;
17681 case TS_CMD_NOT_DEFINED:
17682 subject = "UNKNOWN";
17683 break;
17684 }
17685
17686
2/3
✓ Branch 0 taken 217 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
220 switch (alter_info->ts_cmd_type) {
17687 217 case CREATE_TABLESPACE:
17688 case ALTER_TABLESPACE:
17689 case DROP_TABLESPACE:
17690 case CREATE_UNDO_TABLESPACE:
17691 case ALTER_UNDO_TABLESPACE:
17692 case DROP_UNDO_TABLESPACE:
17693
1/2
✓ Branch 0 taken 217 times.
✗ Branch 1 not taken.
217 ib_errf(thd, IB_LOG_LEVEL_ERROR, code, "%s %s", subject,
17694 alter_info->tablespace_name);
17695 217 break;
17696
17697 3 case CREATE_LOGFILE_GROUP:
17698 case ALTER_ACCESS_MODE_TABLESPACE:
17699 case DROP_LOGFILE_GROUP:
17700 case ALTER_LOGFILE_GROUP:
17701 case CHANGE_FILE_TABLESPACE:
17702 case TS_CMD_NOT_DEFINED:
17703
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_FEATURE_UNSUPPORTED, MYF(0), subject, "by InnoDB");
17704 3 break;
17705 }
17706 }
17707
17708 8876 return error;
17709 8876 }
17710
17711 /** Renames an InnoDB table.
17712 @param[in] from Old name of the table.
17713 @param[in] to New name of the table.
17714 @param[in] from_table_def dd::Table object describing old version
17715 of table.
17716 @param[in,out] to_table_def dd::Table object describing version of
17717 table with new name. Can be updated by SE. Changes are persisted to the
17718 dictionary at statement commit time.
17719 @return 0 or error code */
17720 14361 int ha_innobase::rename_table(const char *from, const char *to,
17721 const dd::Table *from_table_def,
17722 dd::Table *to_table_def) {
17723
1/2
✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
14361 THD *thd = ha_thd();
17724
1/2
✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
14361 trx_t *trx = check_trx_exists(thd);
17725
1/2
✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
14361 TrxInInnoDB trx_in_innodb(trx);
17726
17727
1/2
✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
14361 DBUG_TRACE;
17728
3/6
✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14361 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14361 times.
14361 ut_ad(from_table_def->se_private_id() == to_table_def->se_private_id());
17729
5/10
✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14361 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14361 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14361 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 14361 times.
14361 ut_ad(from_table_def->se_private_data().raw_string() ==
17730 to_table_def->se_private_data().raw_string());
17731
17732
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14358 times.
14361 if (high_level_read_only) {
17733
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
17734 3 return HA_ERR_TABLE_READONLY;
17735 }
17736
17737
4/6
✓ Branch 0 taken 14358 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14358 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 14356 times.
14358 if (dict_sys_t::is_dd_table_id(to_table_def->se_private_id())) {
17738
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_NOT_ALLOWED_COMMAND, MYF(0));
17739 2 return HA_ERR_UNSUPPORTED;
17740 }
17741
17742
1/2
✓ Branch 0 taken 14356 times.
✗ Branch 1 not taken.
14356 innobase_register_trx(ht, thd, trx);
17743
17744
1/2
✓ Branch 0 taken 14311 times.
✗ Branch 1 not taken.
14356 return innobase_basic_ddl::rename_impl<dd::Table>(
17745 14311 thd, from, to, from_table_def, to_table_def, nullptr);
17746 14316 }
17747
17748 /** Returns the exact number of records that this client can see using this
17749 handler object.
17750 @return Error code in case something goes wrong.
17751 These errors will abort the current query:
17752 case HA_ERR_LOCK_DEADLOCK:
17753 case HA_ERR_LOCK_TABLE_FULL:
17754 case HA_ERR_LOCK_WAIT_TIMEOUT:
17755 case HA_ERR_QUERY_INTERRUPTED:
17756 For other error codes, the server will fall back to counting records. */
17757
17758 34683 int ha_innobase::records(ha_rows *num_rows) /*!< out: number of rows */
17759 {
17760
1/2
✓ Branch 0 taken 34683 times.
✗ Branch 1 not taken.
34683 DBUG_TRACE;
17761
17762 dberr_t ret;
17763 34683 ulint n_rows = 0; /* Record count in this view */
17764
17765
1/2
✓ Branch 0 taken 34683 times.
✗ Branch 1 not taken.
34683 update_thd();
17766
17767
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 34647 times.
34683 if (dict_table_is_discarded(m_prebuilt->table)) {
17768 36 ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
17769
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 table->s->table_name.str);
17770
17771 36 *num_rows = HA_POS_ERROR;
17772 36 return HA_ERR_NO_SUCH_TABLE;
17773
17774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34647 times.
34647 } else if (m_prebuilt->table->ibd_file_missing) {
17775 ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING,
17776 table->s->table_name.str);
17777
17778 *num_rows = HA_POS_ERROR;
17779 return HA_ERR_TABLESPACE_MISSING;
17780
17781
2/4
✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34647 times.
34647 } else if (m_prebuilt->table->is_corrupted()) {
17782 ib_errf(m_user_thd, IB_LOG_LEVEL_WARN, ER_INNODB_INDEX_CORRUPT,
17783 "Table '%s' is corrupt.", table->s->table_name.str);
17784
17785 *num_rows = HA_POS_ERROR;
17786 return HA_ERR_INDEX_CORRUPT;
17787 }
17788
17789
1/2
✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
34647 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
17790
17791 34647 m_prebuilt->trx->op_info = "counting records";
17792
17793
1/2
✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
34647 dict_index_t *index = m_prebuilt->table->first_index();
17794
17795
2/4
✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34647 times.
34647 ut_ad(index->is_clustered());
17796
17797
1/2
✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
34647 m_prebuilt->index_usable = index->is_usable(m_prebuilt->trx);
17798
17799
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34646 times.
34647 if (!m_prebuilt->index_usable) {
17800 1 *num_rows = HA_POS_ERROR;
17801 1 return HA_ERR_TABLE_DEF_CHANGED;
17802 }
17803
17804 /* (Re)Build the m_prebuilt->mysql_template if it is null to use
17805 the clustered index and just the key, no off-record data. */
17806 34646 m_prebuilt->index = index;
17807
1/2
✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
34646 m_prebuilt->clear_search_tuples();
17808 34646 m_prebuilt->read_just_key = 1;
17809
1/2
✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
34646 build_template(false);
17810
17811
1/2
✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
34646 size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd);
17812
17813 /* Count the records in the clustered index */
17814 ret =
17815
1/2
✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
34646 row_scan_index_for_mysql(m_prebuilt, index, max_threads, false, &n_rows);
17816
1/2
✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
34646 reset_template();
17817
3/4
✓ Branch 0 taken 34617 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
34646 switch (ret) {
17818 34617 case DB_SUCCESS:
17819 34617 break;
17820 27 case DB_DEADLOCK:
17821 case DB_LOCK_TABLE_FULL:
17822 case DB_LOCK_WAIT_TIMEOUT:
17823 27 *num_rows = HA_POS_ERROR;
17824
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 return convert_error_code_to_mysql(ret, 0, m_user_thd);
17825 2 case DB_INTERRUPTED:
17826 2 *num_rows = HA_POS_ERROR;
17827 2 return HA_ERR_QUERY_INTERRUPTED;
17828 default:
17829 /* No other error besides the three below is returned from
17830 row_scan_index_for_mysql(). Make a debug catch. */
17831 *num_rows = HA_POS_ERROR;
17832 return -1;
17833 }
17834
17835 34617 m_prebuilt->trx->op_info = "";
17836
17837
2/4
✓ Branch 0 taken 34617 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34617 times.
34617 if (thd_killed(m_user_thd)) {
17838 *num_rows = HA_POS_ERROR;
17839 return HA_ERR_QUERY_INTERRUPTED;
17840 }
17841
17842 34617 *num_rows = n_rows;
17843 34617 return 0;
17844 34683 }
17845
17846 /** Estimates the number of index records in a range.
17847 @return estimated number of rows */
17848
17849 487753 ha_rows ha_innobase::records_in_range(
17850 uint keynr, /*!< in: index number */
17851 key_range *min_key, /*!< in: start key value of the
17852 range, may also be 0 */
17853 key_range *max_key) /*!< in: range end key val, may
17854 also be 0 */
17855 {
17856 KEY *key;
17857 dict_index_t *index;
17858 dtuple_t *range_start;
17859 dtuple_t *range_end;
17860 int64_t n_rows;
17861 page_cur_mode_t mode1;
17862 page_cur_mode_t mode2;
17863 mem_heap_t *heap;
17864
17865
1/2
✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
487753 DBUG_TRACE;
17866
17867
3/6
✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 487754 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 487754 times.
487754 ut_a(m_prebuilt->trx == thd_to_trx(ha_thd()));
17868
17869 487754 m_prebuilt->trx->op_info = "estimating records in index range";
17870
17871
1/2
✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
487754 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
17872
17873 487754 active_index = keynr;
17874
17875 487754 key = table->key_info + active_index;
17876
17877
1/2
✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
487754 index = innobase_get_index(keynr);
17878
17879 /* There exists possibility of not being able to find requested
17880 index due to inconsistency between MySQL and InoDB dictionary info.
17881 Necessary message should have been printed in innobase_get_index() */
17882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 487754 times.
487754 if (dict_table_is_discarded(m_prebuilt->table)) {
17883 n_rows = HA_POS_ERROR;
17884 goto func_exit;
17885 }
17886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 487754 times.
487754 if (!index) {
17887 n_rows = HA_POS_ERROR;
17888 goto func_exit;
17889 }
17890
3/4
✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 487746 times.
487754 if (index->is_corrupted()) {
17891 8 n_rows = HA_ERR_INDEX_CORRUPT;
17892 8 goto func_exit;
17893 }
17894
3/4
✓ Branch 0 taken 487746 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 487744 times.
487746 if (!index->is_usable(m_prebuilt->trx)) {
17895 2 n_rows = HA_ERR_TABLE_DEF_CHANGED;
17896 2 goto func_exit;
17897 }
17898
17899 975488 heap = mem_heap_create(
17900
1/2
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
487744 2 * (key->actual_key_parts * sizeof(dfield_t) + sizeof(dtuple_t)),
17901 UT_LOCATION_HERE);
17902
17903
1/2
✓ Branch 0 taken 487743 times.
✗ Branch 1 not taken.
487744 range_start = dtuple_create(heap, key->actual_key_parts);
17904
1/2
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
487743 dict_index_copy_types(range_start, index, key->actual_key_parts);
17905
17906
1/2
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
487744 range_end = dtuple_create(heap, key->actual_key_parts);
17907
1/2
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
487744 dict_index_copy_types(range_end, index, key->actual_key_parts);
17908
17909
4/4
✓ Branch 0 taken 482327 times.
✓ Branch 1 taken 5417 times.
✓ Branch 2 taken 482327 times.
✓ Branch 3 taken 5417 times.
970071 row_sel_convert_mysql_key_to_innobase(
17910
1/2
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
487744 range_start, m_prebuilt->srch_key_val1, m_prebuilt->srch_key_val_len,
17911 index, (byte *)(min_key ? min_key->key : (const uchar *)nullptr),
17912 482327 (ulint)(min_key ? min_key->length : 0));
17913
17914
3/4
✓ Branch 0 taken 482327 times.
✓ Branch 1 taken 5417 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 487744 times.
487744 assert(min_key ? range_start->n_fields > 0 : range_start->n_fields == 0);
17915
17916
4/4
✓ Branch 0 taken 409197 times.
✓ Branch 1 taken 78547 times.
✓ Branch 2 taken 409197 times.
✓ Branch 3 taken 78547 times.
896941 row_sel_convert_mysql_key_to_innobase(
17917
1/2
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
487744 range_end, m_prebuilt->srch_key_val2, m_prebuilt->srch_key_val_len, index,
17918 (byte *)(max_key ? max_key->key : (const uchar *)nullptr),
17919 409197 (ulint)(max_key ? max_key->length : 0));
17920
17921
3/4
✓ Branch 0 taken 409197 times.
✓ Branch 1 taken 78547 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 487744 times.
487744 assert(max_key ? range_end->n_fields > 0 : range_end->n_fields == 0);
17922
17923
3/4
✓ Branch 0 taken 482327 times.
✓ Branch 1 taken 5417 times.
✓ Branch 2 taken 487744 times.
✗ Branch 3 not taken.
487744 mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag
17924 : HA_READ_KEY_EXACT);
17925
17926
3/4
✓ Branch 0 taken 409196 times.
✓ Branch 1 taken 78548 times.
✓ Branch 2 taken 487743 times.
✗ Branch 3 not taken.
487744 mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag
17927 : HA_READ_KEY_EXACT);
17928
17929
2/4
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 487744 times.
✗ Branch 3 not taken.
487743 if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) {
17930
3/4
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 441 times.
✓ Branch 3 taken 487303 times.
487744 if (dict_index_is_spatial(index)) {
17931 /*Only min_key used in spatial index. */
17932
1/2
✓ Branch 0 taken 441 times.
✗ Branch 1 not taken.
441 n_rows = rtr_estimate_n_rows_in_range(index, range_start, mode1);
17933 } else {
17934
1/2
✓ Branch 0 taken 487303 times.
✗ Branch 1 not taken.
487303 n_rows = btr_estimate_n_rows_in_range(index, range_start, mode1,
17935 range_end, mode2);
17936 }
17937 } else {
17938 n_rows = HA_POS_ERROR;
17939 }
17940
17941
1/2
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
487743 mem_heap_free(heap);
17942
17943
5/8
✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 487596 times.
✓ Branch 3 taken 148 times.
✓ Branch 4 taken 148 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 148 times.
✗ Branch 7 not taken.
487744 DBUG_EXECUTE_IF(
17944 "print_btr_estimate_n_rows_in_range_return_value",
17945 push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_NO_DEFAULT,
17946 "btr_estimate_n_rows_in_range(): %" PRId64, n_rows););
17947
17948 487596 func_exit:
17949
17950 487754 m_prebuilt->trx->op_info = (char *)"";
17951
17952 /* The MySQL optimizer seems to believe an estimate of 0 rows is
17953 always accurate and may return the result 'Empty set' based on that.
17954 The accuracy is not guaranteed, and even if it were, for a locking
17955 read we should anyway perform the search to set the next-key lock.
17956 Add 1 to the value to make sure MySQL does not make the assumption! */
17957
17958
2/2
✓ Branch 0 taken 184023 times.
✓ Branch 1 taken 303731 times.
487754 if (n_rows == 0) {
17959 184023 n_rows = 1;
17960 }
17961
17962 487754 return (ha_rows)n_rows;
17963 487754 }
17964
17965 /** Gives an UPPER BOUND to the number of rows in a table. This is used in
17966 filesort.cc.
17967 @return upper bound of rows */
17968
17969 140233 ha_rows ha_innobase::estimate_rows_upper_bound() {
17970 const dict_index_t *index;
17971 ulonglong estimate;
17972 ulonglong local_data_file_length;
17973
17974
1/2
✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
140233 DBUG_TRACE;
17975
17976 /* We do not know if MySQL can call this function before calling
17977 external_lock(). To be safe, update the thd of the current table
17978 handle. */
17979
17980
2/4
✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 140233 times.
✗ Branch 3 not taken.
140233 update_thd(ha_thd());
17981
17982
1/2
✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
140233 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
17983
17984 140233 m_prebuilt->trx->op_info = "calculating upper bound for table rows";
17985
17986
1/2
✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
140233 index = m_prebuilt->table->first_index();
17987
17988 140233 ulint stat_n_leaf_pages = index->stat_n_leaf_pages;
17989
17990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140233 times.
140233 ut_a(stat_n_leaf_pages > 0);
17991
17992 140233 local_data_file_length = ((ulonglong)stat_n_leaf_pages) * UNIV_PAGE_SIZE;
17993
17994 /* Calculate a minimum length for a clustered index record and from
17995 that an upper bound for the number of rows. Since we only calculate
17996 new statistics in row0mysql.cc when a table has grown by a threshold
17997 factor, we must add a safety factor 2 in front of the formula below. */
17998
17999
1/2
✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
140233 estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
18000
18001 140233 m_prebuilt->trx->op_info = "";
18002
18003 /* Set num_rows less than MERGEBUFF to simulate the case where we do
18004 not have enough space to merge the externally sorted file blocks. */
18005
2/6
✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 140233 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
140233 DBUG_EXECUTE_IF("set_num_rows_lt_MERGEBUFF", estimate = 2;
18006 DBUG_SET("-d,set_num_rows_lt_MERGEBUFF"););
18007
18008 140233 return (ha_rows)estimate;
18009 140233 }
18010
18011 /** How many seeks it will take to read through the table. This is to be
18012 comparable to the number returned by records_in_range so that we can
18013 decide if we should scan the table or use keys.
18014 @return estimated time measured in disk seeks */
18015
18016 79325649 double ha_innobase::scan_time() {
18017 /* Since MySQL seems to favor table scans too much over index
18018 searches, we pretend that a sequential read takes the same time
18019 as a random disk read, that is, we do not divide the following
18020 by 10, which would be physically realistic. */
18021
18022 /* The locking below is disabled for performance reasons. Without
18023 it we could end up returning uninitialized value to the caller,
18024 which in the worst case could make some query plan go bogus or
18025 issue a Valgrind warning. */
18026
18027
2/2
✓ Branch 0 taken 1429 times.
✓ Branch 1 taken 79324220 times.
79325649 if (m_prebuilt == nullptr) {
18028 /* In case of derived table, Optimizer will try to fetch stat
18029 for table even before table is create or open. In such
18030 cases return default value of 1.
18031 TODO: This will be further improved to return some approximate
18032 estimate but that would also needs pre-population of stats
18033 structure. As of now approach is in sync with MyISAM. */
18034 1429 return (ulonglong2double(stats.data_file_length) / IO_SIZE + 2);
18035 }
18036
18037 ulint stat_clustered_index_size;
18038
18039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79324297 times.
79324220 ut_a(m_prebuilt->table->stat_initialized);
18040
18041 79324297 stat_clustered_index_size = m_prebuilt->table->stat_clustered_index_size;
18042
18043 79324297 return ((double)stat_clustered_index_size);
18044 }
18045
18046 /** Calculate the time it takes to read a set of ranges through an index
18047 This enables us to optimise reads for clustered indexes.
18048 @return estimated time measured in disk seeks */
18049
18050 760552 double ha_innobase::read_time(
18051 uint index, /*!< in: key number */
18052 uint ranges, /*!< in: how many ranges */
18053 ha_rows rows) /*!< in: estimated number of rows in the ranges */
18054 {
18055 ha_rows total_rows;
18056
18057
2/2
✓ Branch 0 taken 356817 times.
✓ Branch 1 taken 403735 times.
760552 if (index != table->s->primary_key) {
18058 /* Not clustered */
18059 356817 return (handler::read_time(index, ranges, rows));
18060 }
18061
18062
2/2
✓ Branch 0 taken 262922 times.
✓ Branch 1 taken 140813 times.
403735 if (rows <= 2) {
18063 262922 return ((double)rows);
18064 }
18065
18066 /* Assume that the read time is proportional to the scan time for all
18067 rows + at most one seek per range. */
18068
18069 140813 double time_for_scan = scan_time();
18070
18071
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 140836 times.
140837 if ((total_rows = estimate_rows_upper_bound()) < rows) {
18072 1 return (time_for_scan);
18073 }
18074
18075 140836 return (ranges + (double)rows / (double)total_rows * time_for_scan);
18076 }
18077
18078 /** Return the size of the InnoDB memory buffer. */
18079
18080 2091035 longlong ha_innobase::get_memory_buffer_size() const {
18081 2091035 return (srv_buf_pool_curr_size);
18082 }
18083
18084 /** Update the system variable with the given value of the InnoDB
18085 buffer pool size.
18086 @param[in] buf_pool_size given value of buffer pool size.*/
18087 23 void innodb_set_buf_pool_size(long long buf_pool_size) {
18088 23 srv_buf_pool_curr_size = buf_pool_size;
18089 23 }
18090
18091 /** Calculates the key number used inside MySQL for an Innobase index. We
18092 will first check the "index translation table" for a match of the index to
18093 get the index number. If there does not exist an "index translation table",
18094 or not able to find the index in the translation table, then we will fall
18095 back to the traditional way of looping through dict_index_t list to find a
18096 match. In this case, we have to take into account if we generated a
18097 default clustered index for the table
18098 @return the key number used inside MySQL */
18099 488670 static int innobase_get_mysql_key_number_for_index(
18100 INNOBASE_SHARE *share, /*!< in: share structure for index
18101 translation table. */
18102 const TABLE *table, /*!< in: table in MySQL data
18103 dictionary */
18104 dict_table_t *ib_table, /*!< in: table in InnoDB data
18105 dictionary */
18106 const dict_index_t *index) /*!< in: index */
18107 {
18108 const dict_index_t *ind;
18109 unsigned int i;
18110
18111 /* If index does not belong to the table object of share structure
18112 (ib_table comes from the share structure) search the index->table
18113 object instead */
18114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 488670 times.
488670 if (index->table != ib_table) {
18115 i = 0;
18116 ind = index->table->first_index();
18117
18118 while (index != ind) {
18119 ind = ind->next();
18120 i++;
18121 }
18122
18123 if (row_table_got_default_clust_index(index->table)) {
18124 ut_a(i > 0);
18125 i--;
18126 }
18127
18128 return (i);
18129 }
18130
18131 /* If index translation table exists, we will first check
18132 the index through index translation table for a match. */
18133
1/2
✓ Branch 0 taken 488670 times.
✗ Branch 1 not taken.
488670 if (share->idx_trans_tbl.index_mapping != nullptr) {
18134
1/2
✓ Branch 0 taken 488870 times.
✗ Branch 1 not taken.
488870 for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
18135
2/2
✓ Branch 0 taken 488670 times.
✓ Branch 1 taken 200 times.
488870 if (share->idx_trans_tbl.index_mapping[i] == index) {
18136 488670 return (i);
18137 }
18138 }
18139
18140 /* Print an error message if we cannot find the index
18141 in the "index translation table". */
18142 if (index->is_committed()) {
18143 log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX, index->name());
18144 }
18145 }
18146
18147 /* If we do not have an "index translation table", or not able
18148 to find the index in the translation table, we'll directly find
18149 matching index with information from mysql TABLE structure and
18150 InnoDB dict_index_t list */
18151 for (i = 0; i < table->s->keys; i++) {
18152 ind = dict_table_get_index_on_name(ib_table, table->key_info[i].name);
18153
18154 if (index == ind) {
18155 return (i);
18156 }
18157 }
18158
18159 /* Loop through each index of the table and lock them */
18160 for (ind = ib_table->first_index(); ind != nullptr; ind = ind->next()) {
18161 if (index == ind) {
18162 /* Temp index is internal to InnoDB, that is
18163 not present in the MySQL index list, so no
18164 need to print such mismatch warning. */
18165 if (index->is_committed()) {
18166 log_errlog(WARNING_LEVEL, ER_INNODB_INTERNAL_INDEX, index->name());
18167 }
18168 return (-1);
18169 }
18170 }
18171
18172 ut_error;
18173 }
18174
18175 /** Calculate Record Per Key value.
18176 Need to exclude the NULL value if innodb_stats_method is set to "nulls_ignored"
18177 @param[in] index InnoDB index.
18178 @param[in] i The column we are calculating rec per key.
18179 @param[in] records Estimated total records.
18180 @return estimated record per key value */
18181 48242139 rec_per_key_t innodb_rec_per_key(const dict_index_t *index, ulint i,
18182 ha_rows records) {
18183 rec_per_key_t rec_per_key;
18184 uint64_t n_diff;
18185
18186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48242148 times.
48242139 ut_a(index->table->stat_initialized);
18187
18188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48242143 times.
48242148 ut_ad(i < dict_index_get_n_unique(index));
18189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48242161 times.
48242143 ut_ad(!dict_index_is_spatial(index));
18190
18191
2/2
✓ Branch 0 taken 6376617 times.
✓ Branch 1 taken 41865544 times.
48242161 if (records == 0) {
18192 /* "Records per key" is meaningless for empty tables.
18193 Return 1.0 because that is most convenient to the Optimizer. */
18194 6376617 return (1.0);
18195 }
18196
18197 41865544 n_diff = index->stat_n_diff_key_vals[i];
18198
18199
2/2
✓ Branch 0 taken 6601355 times.
✓ Branch 1 taken 35264189 times.
41865544 if (n_diff == 0) {
18200 6601355 rec_per_key = static_cast<rec_per_key_t>(records);
18201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35264189 times.
35264189 } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) {
18202 uint64_t n_null;
18203 uint64_t n_non_null;
18204
18205 n_non_null = index->stat_n_non_null_key_vals[i];
18206
18207 /* In theory, index->stat_n_non_null_key_vals[i]
18208 should always be less than the number of records.
18209 Since this is statistics value, the value could
18210 have slight discrepancy. But we will make sure
18211 the number of null values is not a negative number. */
18212 if (records < n_non_null) {
18213 n_null = 0;
18214 } else {
18215 n_null = records - n_non_null;
18216 }
18217
18218 /* If the number of NULL values is the same as or
18219 large than that of the distinct values, we could
18220 consider that the table consists mostly of NULL value.
18221 Set rec_per_key to 1. */
18222 if (n_diff <= n_null) {
18223 rec_per_key = 1.0;
18224 } else {
18225 /* Need to exclude rows with NULL values from
18226 rec_per_key calculation */
18227 rec_per_key =
18228 static_cast<rec_per_key_t>(records - n_null) / (n_diff - n_null);
18229 }
18230 } else {
18231 #ifdef UNIV_DEBUG
18232
2/2
✓ Branch 0 taken 4457235 times.
✓ Branch 1 taken 30806954 times.
35264189 if (!index->table->is_dd_table) {
18233
2/2
✓ Branch 0 taken 4445033 times.
✓ Branch 1 taken 12202 times.
4457235 DEBUG_SYNC_C("after_checking_for_0");
18234 }
18235 #endif /* UNIV_DEBUG */
18236 35264202 rec_per_key = static_cast<rec_per_key_t>(records) / n_diff;
18237 }
18238
18239
2/2
✓ Branch 0 taken 3115049 times.
✓ Branch 1 taken 38750508 times.
41865557 if (rec_per_key < 1.0) {
18240 /* Values below 1.0 are meaningless and must be due to the
18241 stats being imprecise. */
18242 3115049 rec_per_key = 1.0;
18243 }
18244
18245 41865557 return (rec_per_key);
18246 }
18247
18248 /** Read the auto_increment counter of a table, using the AUTOINC lock
18249 irrespective of innodb_autoinc_lock_mode.
18250 @param[in,out] innodb_table InnoDB table object
18251 @param[in] print_note Print note if not an I_S query.
18252 @return the autoinc value */
18253 16591 static ulonglong innobase_peek_autoinc(dict_table_t *innodb_table,
18254 bool print_note) {
18255 ulonglong auto_inc;
18256
18257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16591 times.
16591 ut_a(innodb_table != nullptr);
18258
18259 16591 dict_table_autoinc_lock(innodb_table);
18260
18261 16591 auto_inc = dict_table_autoinc_read(innodb_table);
18262
18263
3/4
✓ Branch 0 taken 3071 times.
✓ Branch 1 taken 13520 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3071 times.
16591 if (auto_inc == 0 && print_note) {
18264 ib::info(ER_IB_MSG_569) << "AUTOINC next value generation is disabled for "
18265 << innodb_table->name;
18266 }
18267
18268 16591 dict_table_autoinc_unlock(innodb_table);
18269
18270 16591 return (auto_inc);
18271 }
18272
18273 /** Calculate delete length statistic.
18274 @param[in] ib_table table object
18275 @param[in,out] stats stats structure to hold calculated values
18276 @param[in,out] thd user thread handle (for issuing warnings) */
18277 10570 static void calculate_delete_length_stat(const dict_table_t *ib_table,
18278 ha_statistics *stats, THD *thd) {
18279 uintmax_t avail_space;
18280
18281 10570 avail_space = fsp_get_available_space_in_free_extents(ib_table->space);
18282
18283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10570 times.
10570 if (avail_space == UINTMAX_MAX) {
18284 char errbuf[MYSYS_STRERROR_SIZE];
18285 std::ostringstream err_msg;
18286 err_msg << "InnoDB: Trying to get the free space for table "
18287 << ib_table->name
18288 << " but its tablespace has been"
18289 " discarded or the .ibd file is missing. Setting"
18290 " the free space to zero. (errno: "
18291 << errno << " - " << my_strerror(errbuf, sizeof(errbuf), errno)
18292 << ")";
18293
18294 push_warning(thd, Sql_condition::SL_WARNING, ER_CANT_GET_STAT,
18295 err_msg.str().c_str());
18296
18297 stats->delete_length = 0;
18298 } else {
18299 10570 stats->delete_length = avail_space * 1024;
18300 }
18301 10570 }
18302
18303 /** Calculate stats based on index size.
18304 @param[in] ib_table table object
18305 @param[in] n_rows number of rows
18306 @param[in] stat_clustered_index_size clustered index size
18307 @param[in] stat_sum_of_other_index_sizes sum of non-clustered index sizes
18308 @param[in,out] stats the stats structure to hold
18309 calculated values */
18310 8698707 static void calculate_index_size_stats(const dict_table_t *ib_table,
18311 uint64_t n_rows,
18312 ulint stat_clustered_index_size,
18313 ulint stat_sum_of_other_index_sizes,
18314 ha_statistics *stats) {
18315
1/2
✓ Branch 0 taken 8698745 times.
✗ Branch 1 not taken.
8698707 const page_size_t &page_size = dict_table_page_size(ib_table);
18316
18317 8698745 stats->records = static_cast<ha_rows>(n_rows);
18318 8698762 stats->data_file_length =
18319
1/2
✓ Branch 0 taken 8698762 times.
✗ Branch 1 not taken.
8698745 static_cast<ulonglong>(stat_clustered_index_size) * page_size.physical();
18320 8698802 stats->index_file_length =
18321 8698802 static_cast<ulonglong>(stat_sum_of_other_index_sizes) *
18322
1/2
✓ Branch 0 taken 8698802 times.
✗ Branch 1 not taken.
8698762 page_size.physical();
18323
2/2
✓ Branch 0 taken 530952 times.
✓ Branch 1 taken 8167850 times.
8698802 if (stats->records == 0) {
18324 530952 stats->mean_rec_length = 0;
18325 } else {
18326 8167850 stats->mean_rec_length =
18327 8167850 static_cast<ulong>(stats->data_file_length / stats->records);
18328 }
18329 8698802 }
18330
18331 /** Estimate what percentage of an index's pages are cached in the buffer pool
18332 @param[in] index index whose pages to look up
18333 @return a real number in [0.0, 1.0] designating the percentage of cached pages
18334 */
18335 23843449 inline double index_pct_cached(const dict_index_t *index) {
18336 23843449 const ulint n_leaf = index->stat_n_leaf_pages;
18337
18338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23843449 times.
23843449 if (n_leaf == 0) {
18339 return (0.0);
18340 }
18341
18342 const uint64_t n_in_mem =
18343
1/2
✓ Branch 0 taken 23843511 times.
✗ Branch 1 not taken.
23843449 buf_stat_per_index->get(index_id_t(index->space, index->id));
18344
18345 23843511 const double ratio = static_cast<double>(n_in_mem) / n_leaf;
18346
18347 23843511 return (std::max(std::min(ratio, 1.0), 0.0));
18348 }
18349
18350 /** Returns statistics information of the table to the MySQL interpreter, in
18351 various fields of the handle object.
18352 @param[in] flag what information is requested
18353 @param[in] is_analyze True if called from "::analyze()".
18354 @return HA_ERR_* error code or 0 */
18355 9289488 int ha_innobase::info_low(uint flag, bool is_analyze) {
18356 dict_table_t *ib_table;
18357 uint64_t n_rows;
18358
18359
1/2
✓ Branch 0 taken 9289603 times.
✗ Branch 1 not taken.
9289488 DBUG_TRACE;
18360
18361
3/4
✓ Branch 0 taken 9157907 times.
✓ Branch 1 taken 131696 times.
✓ Branch 2 taken 9157934 times.
✗ Branch 3 not taken.
9289603 DEBUG_SYNC_C("ha_innobase_info_low");
18362
18363 /* If we are forcing recovery at a high level, we will suppress
18364 statistics calculation on tables, because that may crash the
18365 server if an index is badly corrupted. */
18366
18367 /* We do not know if MySQL can call this function before calling
18368 external_lock(). To be safe, update the thd of the current table
18369 handle. */
18370
18371
2/4
✓ Branch 0 taken 9289612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9289606 times.
✗ Branch 3 not taken.
9289630 update_thd(ha_thd());
18372
18373 9289606 m_prebuilt->trx->op_info = (char *)"returning various info to MySQL";
18374
18375 9289606 ib_table = m_prebuilt->table;
18376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9289601 times.
9289606 assert(ib_table->n_ref_count > 0);
18377
18378
2/2
✓ Branch 0 taken 132854 times.
✓ Branch 1 taken 9156747 times.
9289601 if (flag & HA_STATUS_TIME) {
18379
4/4
✓ Branch 0 taken 127330 times.
✓ Branch 1 taken 5524 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 127258 times.
132854 if (is_analyze || innobase_stats_on_metadata) {
18380 dict_stats_upd_option_t opt;
18381 dberr_t ret;
18382
18383 5596 m_prebuilt->trx->op_info = "updating table statistics";
18384
18385
3/4
✓ Branch 0 taken 5596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5404 times.
✓ Branch 3 taken 192 times.
5596 if (dict_stats_is_persistent_enabled(ib_table)) {
18386
2/2
✓ Branch 0 taken 5332 times.
✓ Branch 1 taken 72 times.
5404 if (is_analyze) {
18387 /* If this table is already queued for background analyze, remove it
18388 from the queue as we are about to do the same */
18389
2/2
✓ Branch 0 taken 5329 times.
✓ Branch 1 taken 3 times.
5332 if (!srv_read_only_mode) {
18390
1/2
✓ Branch 0 taken 5329 times.
✗ Branch 1 not taken.
5329 dict_mutex_enter_for_mysql();
18391
1/2
✓ Branch 0 taken 5329 times.
✗ Branch 1 not taken.
5329 dict_stats_recalc_pool_del(ib_table);
18392
1/2
✓ Branch 0 taken 5329 times.
✗ Branch 1 not taken.
5329 dict_mutex_exit_for_mysql();
18393 }
18394 5332 opt = DICT_STATS_RECALC_PERSISTENT;
18395 } else {
18396 /* This is e.g. 'SHOW INDEXES', fetch
18397 the persistent stats from disk. */
18398 72 opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY;
18399 }
18400 } else {
18401 192 opt = DICT_STATS_RECALC_TRANSIENT;
18402 }
18403
18404
2/4
✓ Branch 0 taken 5596 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5596 times.
5596 ut_ad(!dict_sys_mutex_own());
18405
1/2
✓ Branch 0 taken 5596 times.
✗ Branch 1 not taken.
5596 ret = dict_stats_update(ib_table, opt);
18406
18407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5596 times.
5596 if (ret != DB_SUCCESS) {
18408 m_prebuilt->trx->op_info = "";
18409 return HA_ERR_GENERIC;
18410 }
18411
18412 5596 m_prebuilt->trx->op_info = "returning various info to MySQL";
18413 }
18414
18415 132854 stats.update_time = (ulong)std::chrono::system_clock::to_time_t(
18416 265708 ib_table->update_time.load());
18417 }
18418
18419
2/2
✓ Branch 0 taken 8695253 times.
✓ Branch 1 taken 594348 times.
9289601 if (flag & HA_STATUS_VARIABLE) {
18420 ulint stat_clustered_index_size;
18421 ulint stat_sum_of_other_index_sizes;
18422
18423
2/2
✓ Branch 0 taken 19842 times.
✓ Branch 1 taken 8675411 times.
8695253 if (!(flag & HA_STATUS_NO_LOCK)) {
18424
1/2
✓ Branch 0 taken 19842 times.
✗ Branch 1 not taken.
19842 dict_table_stats_lock(ib_table, RW_S_LATCH);
18425 }
18426
18427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8695231 times.
8695253 ut_a(ib_table->stat_initialized);
18428
18429 8695231 n_rows = ib_table->stat_n_rows;
18430
18431 8695231 stat_clustered_index_size = ib_table->stat_clustered_index_size;
18432
18433 8695231 stat_sum_of_other_index_sizes = ib_table->stat_sum_of_other_index_sizes;
18434
18435
2/2
✓ Branch 0 taken 19842 times.
✓ Branch 1 taken 8675389 times.
8695231 if (!(flag & HA_STATUS_NO_LOCK)) {
18436
1/2
✓ Branch 0 taken 19842 times.
✗ Branch 1 not taken.
19842 dict_table_stats_unlock(ib_table, RW_S_LATCH);
18437 }
18438
18439 /*
18440 The MySQL optimizer seems to assume in a left join that n_rows
18441 is an accurate estimate if it is zero. Of course, it is not,
18442 since we do not have any locks on the rows yet at this phase.
18443 Since SHOW TABLE STATUS seems to call this function with the
18444 HA_STATUS_TIME flag set, while the left join optimizer does not
18445 set that flag, we add one to a zero value if the flag is not
18446 set. That way SHOW TABLE STATUS will show the best estimate,
18447 while the optimizer never sees the table empty.
18448 However, if it is internal temporary table used by optimizer,
18449 the count should be accurate */
18450
18451
4/4
✓ Branch 0 taken 2403358 times.
✓ Branch 1 taken 6291873 times.
✓ Branch 2 taken 2282024 times.
✓ Branch 3 taken 121334 times.
8695231 if (n_rows == 0 && !(flag & HA_STATUS_TIME) &&
18452
2/2
✓ Branch 0 taken 1873949 times.
✓ Branch 1 taken 408075 times.
2282024 table_share->table_category != TABLE_CATEGORY_TEMPORARY) {
18453 1873949 n_rows++;
18454 }
18455
18456 8695231 stats.records = (ha_rows)n_rows;
18457 8695231 stats.deleted = 0;
18458
18459
1/2
✓ Branch 0 taken 8695299 times.
✗ Branch 1 not taken.
8695231 calculate_index_size_stats(ib_table, n_rows, stat_clustered_index_size,
18460 stat_sum_of_other_index_sizes, &stats);
18461
18462 /* Since fsp_get_available_space_in_free_extents() is
18463 acquiring latches inside InnoDB, we do not call it if we
18464 are asked by MySQL to avoid locking. Another reason to
18465 avoid the call is that it uses quite a lot of CPU.
18466 See Bug#38185. */
18467
4/4
✓ Branch 0 taken 19842 times.
✓ Branch 1 taken 8675457 times.
✓ Branch 2 taken 7069 times.
✓ Branch 3 taken 12773 times.
8695299 if (flag & HA_STATUS_NO_LOCK || !(flag & HA_STATUS_VARIABLE_EXTRA)) {
18468 /* We do not update delete_length if no
18469 locking is requested so the "old" value can
18470 remain. delete_length is initialized to 0 in
18471 the ha_statistics' constructor. Also we only
18472 need delete_length to be set when
18473 HA_STATUS_VARIABLE_EXTRA is set */
18474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7069 times.
7069 } else if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
18475 /* Avoid accessing the tablespace if
18476 innodb_crash_recovery is set to a high value. */
18477 stats.delete_length = 0;
18478 } else {
18479
2/4
✓ Branch 0 taken 7069 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7043 times.
✗ Branch 3 not taken.
7069 calculate_delete_length_stat(ib_table, &stats, ha_thd());
18480 }
18481
18482 8695273 stats.check_time = 0;
18483 8695273 stats.mrr_length_per_rec = ref_length + sizeof(void *);
18484 }
18485
18486 /* Verify the number of indexes in InnoDB and MySQL
18487 matches up. If m_prebuilt->clust_index_was_generated
18488 holds, InnoDB defines GEN_CLUST_INDEX internally. */
18489
1/2
✓ Branch 0 taken 9289536 times.
✗ Branch 1 not taken.
9289621 ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) -
18490 9289536 m_prebuilt->clust_index_was_generated;
18491
2/2
✓ Branch 0 taken 6171 times.
✓ Branch 1 taken 9283365 times.
9289536 if (table->s->keys < num_innodb_index) {
18492 /* If there are too many indexes defined
18493 inside InnoDB, ignore those that are being
18494 created, because MySQL will only consider
18495 the fully built indexes here. */
18496
18497
6/10
✓ Branch 0 taken 6171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6171 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28783 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34954 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 28783 times.
✓ Branch 9 taken 6171 times.
34954 for (const dict_index_t *index : ib_table->indexes) {
18498 /* First, online index creation is
18499 completed inside InnoDB, and then
18500 MySQL attempts to upgrade the
18501 meta-data lock so that it can rebuild
18502 the .frm file. If we get here in that
18503 time frame, dict_index_is_online_ddl()
18504 would not hold and the index would
18505 still not be included in TABLE_SHARE. */
18506
3/4
✓ Branch 0 taken 28783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 279 times.
✓ Branch 3 taken 28504 times.
28783 if (!index->is_committed()) {
18507 279 num_innodb_index--;
18508 }
18509 }
18510
18511
4/4
✓ Branch 0 taken 5901 times.
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 5901 times.
✓ Branch 3 taken 270 times.
12072 if (table->s->keys < num_innodb_index &&
18512
2/4
✓ Branch 0 taken 5901 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5901 times.
✗ Branch 3 not taken.
5901 innobase_fts_check_doc_id_index(ib_table, nullptr, nullptr) ==
18513 FTS_EXIST_DOC_ID_INDEX) {
18514 5901 num_innodb_index--;
18515 }
18516 }
18517
18518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9289536 times.
9289536 if (table->s->keys != num_innodb_index) {
18519 log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_MORE_THAN_DEFINED_IN_MYSQL,
18520 ib_table->name.m_name, num_innodb_index, table->s->keys);
18521 }
18522
18523
2/2
✓ Branch 0 taken 125423 times.
✓ Branch 1 taken 9164113 times.
9289536 if (!(flag & HA_STATUS_NO_LOCK)) {
18524
1/2
✓ Branch 0 taken 125423 times.
✗ Branch 1 not taken.
125423 dict_table_stats_lock(ib_table, RW_S_LATCH);
18525 }
18526
18527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9289532 times.
9289536 ut_a(ib_table->stat_initialized);
18528
18529 9289532 const dict_index_t *pk = UT_LIST_GET_FIRST(ib_table->indexes);
18530
18531
2/2
✓ Branch 0 taken 23914680 times.
✓ Branch 1 taken 9289630 times.
33204310 for (uint i = 0; i < table->s->keys; i++) {
18532 ulong j;
18533 /* We could get index quickly through internal
18534 index mapping with the index translation table.
18535 The identity of index (match up index name with
18536 that of table->key_info[i]) is already verified in
18537 innobase_get_index(). */
18538
1/2
✓ Branch 0 taken 23914823 times.
✗ Branch 1 not taken.
23914680 dict_index_t *index = innobase_get_index(i);
18539
18540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23914823 times.
23914823 if (index == nullptr) {
18541 log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_FEWER_THAN_DEFINED_IN_MYSQL,
18542 ib_table->name.m_name, TROUBLESHOOTING_MSG);
18543 break;
18544 }
18545
18546 23914823 KEY *key = &table->key_info[i];
18547
18548 double pct_cached;
18549
18550 /* We do not maintain stats for fulltext or spatial indexes.
18551 Thus, we can't calculate pct_cached below because we need
18552 dict_index_t::stat_n_leaf_pages for that. See
18553 dict_stats_should_ignore_index(). */
18554
4/4
✓ Branch 0 taken 23898963 times.
✓ Branch 1 taken 15860 times.
✓ Branch 2 taken 55467 times.
✓ Branch 3 taken 23843496 times.
23914823 if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) {
18555 71327 pct_cached = IN_MEMORY_ESTIMATE_UNKNOWN;
18556 } else {
18557
1/2
✓ Branch 0 taken 23843421 times.
✗ Branch 1 not taken.
23843496 pct_cached = index_pct_cached(index);
18558 }
18559
18560 23914748 key->set_in_memory_estimate(pct_cached);
18561
18562
2/2
✓ Branch 0 taken 7775709 times.
✓ Branch 1 taken 16139083 times.
23914792 if (index == pk) {
18563 7775709 stats.table_in_mem_estimate = pct_cached;
18564 }
18565
18566
2/2
✓ Branch 0 taken 11604058 times.
✓ Branch 1 taken 12310734 times.
23914792 if (flag & HA_STATUS_CONST) {
18567
2/2
✓ Branch 0 taken 3051 times.
✓ Branch 1 taken 11601005 times.
11604058 if (!key->supports_records_per_key()) {
18568 3051 continue;
18569 }
18570
18571
2/2
✓ Branch 0 taken 24124187 times.
✓ Branch 1 taken 11600993 times.
35725180 for (j = 0; j < key->actual_key_parts; j++) {
18572
4/4
✓ Branch 0 taken 24118965 times.
✓ Branch 1 taken 5222 times.
✓ Branch 2 taken 4140 times.
✓ Branch 3 taken 24114825 times.
24124187 if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) {
18573 /* The record per key does not apply to
18574 FTS or Spatial indexes. */
18575 9362 key->set_records_per_key(j, 1.0f);
18576 9367 continue;
18577 }
18578
18579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24114825 times.
24114825 if (j + 1 > index->n_uniq) {
18580 log_errlog(ERROR_LEVEL, ER_INNODB_IDX_COLUMN_CNT_DIFF, index->name(),
18581 ib_table->name.m_name, (unsigned long)index->n_uniq, j + 1,
18582 TROUBLESHOOTING_MSG);
18583 break;
18584 }
18585
18586 /* innodb_rec_per_key() will use
18587 index->stat_n_diff_key_vals[] and the value we
18588 pass index->table->stat_n_rows. Both are
18589 calculated by ANALYZE and by the background
18590 stats gathering thread (which kicks in when too
18591 much of the table has been changed). In
18592 addition table->stat_n_rows is adjusted with
18593 each DML (e.g. ++ on row insert). Those
18594 adjustments are not MVCC'ed and not even
18595 reversed on rollback. So,
18596 index->stat_n_diff_key_vals[] and
18597 index->table->stat_n_rows could have been
18598 calculated at different time. This is
18599 acceptable. */
18600 const rec_per_key_t rec_per_key =
18601
1/2
✓ Branch 0 taken 24114803 times.
✗ Branch 1 not taken.
24114825 innodb_rec_per_key(index, (ulint)j, index->table->stat_n_rows);
18602
18603 24114803 key->set_records_per_key(j, rec_per_key);
18604
18605 /* The code below is legacy and should be
18606 removed together with this comment once we
18607 are sure the new floating point rec_per_key,
18608 set via set_records_per_key(), works fine. */
18609
18610 ulong rec_per_key_int = static_cast<ulong>(
18611
1/2
✓ Branch 0 taken 24114808 times.
✗ Branch 1 not taken.
24114802 innodb_rec_per_key(index, (ulint)j, stats.records));
18612
18613 /* Since MySQL seems to favor table scans
18614 too much over index searches, we pretend
18615 index selectivity is 2 times better than
18616 our estimate: */
18617
18618 24114808 rec_per_key_int = rec_per_key_int / 2;
18619
18620
2/2
✓ Branch 0 taken 17450042 times.
✓ Branch 1 taken 6664766 times.
24114808 if (rec_per_key_int == 0) {
18621 17450042 rec_per_key_int = 1;
18622 }
18623
18624 24114808 key->rec_per_key[j] = rec_per_key_int;
18625 }
18626 }
18627 }
18628
18629
2/2
✓ Branch 0 taken 125423 times.
✓ Branch 1 taken 9164207 times.
9289630 if (!(flag & HA_STATUS_NO_LOCK)) {
18630
1/2
✓ Branch 0 taken 125336 times.
✗ Branch 1 not taken.
125423 dict_table_stats_unlock(ib_table, RW_S_LATCH);
18631 }
18632
18633
2/2
✓ Branch 0 taken 1736 times.
✓ Branch 1 taken 9287807 times.
9289543 if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
18634 1736 goto func_exit;
18635
18636
2/2
✓ Branch 0 taken 488672 times.
✓ Branch 1 taken 8799135 times.
9287807 } else if (flag & HA_STATUS_ERRKEY) {
18637 const dict_index_t *err_index;
18638
18639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 488672 times.
488672 ut_a(m_prebuilt->trx);
18640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 488672 times.
488672 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
18641
18642 488672 err_index = trx_get_error_index(m_prebuilt->trx);
18643
18644
2/2
✓ Branch 0 taken 488670 times.
✓ Branch 1 taken 2 times.
488672 if (err_index) {
18645
1/2
✓ Branch 0 taken 488670 times.
✗ Branch 1 not taken.
488670 errkey = innobase_get_mysql_key_number_for_index(m_share, table, ib_table,
18646 err_index);
18647 } else {
18648 2 errkey =
18649 (unsigned int)((m_prebuilt->trx->error_key_num == ULINT_UNDEFINED)
18650 ? ~0
18651 2 : m_prebuilt->trx->error_key_num);
18652 }
18653 }
18654
18655
4/4
✓ Branch 0 taken 9174962 times.
✓ Branch 1 taken 112845 times.
✓ Branch 2 taken 99755 times.
✓ Branch 3 taken 13090 times.
9287807 if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
18656
1/2
✓ Branch 0 taken 13090 times.
✗ Branch 1 not taken.
13090 ulonglong auto_inc_val = innobase_peek_autoinc(ib_table, true);
18657 /* Initialize autoinc value if not set. */
18658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13090 times.
13090 if (auto_inc_val == 0) {
18659 dict_table_autoinc_lock(m_prebuilt->table);
18660 innobase_initialize_autoinc();
18661 dict_table_autoinc_unlock(m_prebuilt->table);
18662
18663 auto_inc_val = innobase_peek_autoinc(ib_table, true);
18664 }
18665 13090 stats.auto_increment_value = auto_inc_val;
18666 }
18667
18668 9274717 func_exit:
18669 9289543 m_prebuilt->trx->op_info = (char *)"";
18670
18671 9289543 return 0;
18672 9289543 }
18673
18674 /** Returns statistics information of the table to the MySQL interpreter,
18675 in various fields of the handle object.
18676 @return HA_ERR_* error code or 0 */
18677
18678 9375435 int ha_innobase::info(uint flag) /*!< in: what information is requested */
18679 {
18680 9375435 return (info_low(flag, false /* not ANALYZE */));
18681 }
18682
18683 /** Get the autoincrement for the given table id which is
18684 not in the cache.
18685 @param[in] se_private_id InnoDB table id
18686 @param[in] tbl_se_private_data table SE private data
18687 @return autoincrement value for the given table_id. */
18688 27 static uint64_t innodb_get_auto_increment_for_uncached(
18689 dd::Object_id se_private_id, const dd::Properties &tbl_se_private_data) {
18690 27 uint64_t autoinc = 0;
18691 27 uint64_t meta_autoinc = 0;
18692
18693 bool exists =
18694
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 tbl_se_private_data.exists(dd_table_key_strings[DD_TABLE_AUTOINC]);
18695
18696 /** Get the auto_increment from the table SE private data. */
18697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (exists) {
18698 tbl_se_private_data.get(dd_table_key_strings[DD_TABLE_AUTOINC], &autoinc);
18699 }
18700
18701 /** Get the auto_increment value from innodb_dynamic_metadata
18702 table. */
18703
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 mutex_enter(&dict_persist->mutex);
18704
18705 27 DDTableBuffer *table_buffer = dict_persist->table_buffer;
18706
18707 uint64_t version;
18708
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 std::string *readmeta = table_buffer->get(se_private_id, &version);
18709
18710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (readmeta->length() != 0) {
18711 PersistentTableMetadata metadata(se_private_id, version);
18712
18713 dict_table_read_dynamic_metadata(
18714 reinterpret_cast<const byte *>(readmeta->data()), readmeta->length(),
18715 &metadata);
18716
18717 meta_autoinc = metadata.get_autoinc();
18718 }
18719
18720
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 mutex_exit(&dict_persist->mutex);
18721
18722 27 ut::delete_(readmeta);
18723
18724 27 return (std::max(meta_autoinc, autoinc));
18725 }
18726
18727 /** Retrieves table statistics only for uncache table only.
18728 @param[in] db_name database name
18729 @param[in] tbl_name table name
18730 @param[in] norm_name tablespace name
18731 @param[in] se_private_id InnoDB table id
18732 @param[in] ts_se_private_data tablespace se private data
18733 @param[in] tbl_se_private_data table se private data
18734 @param[in] stat_flags flags used to retrieve specific stats
18735 @param[in,out] stats structure to save the retrieved statistics
18736 @return true if the stats information filled successfully
18737 @return false if tablespace is missing or table doesn't have persistent
18738 stats. */
18739 35 static bool innodb_get_table_statistics_for_uncached(
18740 const char *db_name, const char *tbl_name, const char *norm_name,
18741 dd::Object_id se_private_id, const dd::Properties &ts_se_private_data,
18742 const dd::Properties &tbl_se_private_data, ulint stat_flags,
18743 ha_statistics *stats) {
18744
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 TableStatsRecord stat_info;
18745 space_id_t space_id;
18746
18747
3/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 27 times.
35 if (!row_search_table_stats(db_name, tbl_name, stat_info)) {
18748 8 return (false);
18749 }
18750
18751 /** Server passes dummy ts_se_private_data for file_per_table
18752 tablespace. In that case, InnoDB should find the space_id using
18753 the tablespace name. */
18754
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 bool exists = ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID]);
18755
18756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (exists) {
18757 ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id);
18758 } else {
18759
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 space_id = fil_space_get_id_by_name(norm_name);
18760
18761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (space_id == SPACE_UNKNOWN) {
18762 return (false);
18763 }
18764 }
18765
18766 fil_space_t *space;
18767 uint32_t fsp_flags;
18768
18769
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 space = fil_space_acquire(space_id);
18770
18771 /** Tablespace is missing in this case. */
18772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (space == nullptr) {
18773 return (false);
18774 }
18775
18776 27 fsp_flags = space->flags;
18777
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 page_size_t page_size(fsp_flags);
18778
18779
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (stat_flags & HA_STATUS_VARIABLE_EXTRA) {
18780
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 ulint avail_space = fsp_get_available_space_in_free_extents(space);
18781 27 stats->delete_length = avail_space * 1024;
18782 }
18783
18784
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 fil_space_release(space);
18785
18786
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (stat_flags & HA_STATUS_AUTO) {
18787
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 stats->auto_increment_value = innodb_get_auto_increment_for_uncached(
18788 se_private_id, tbl_se_private_data);
18789 }
18790
18791
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (stat_flags & HA_STATUS_TIME) {
18792 27 stats->update_time = (time_t)NULL;
18793 }
18794
18795
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 if (stat_flags & HA_STATUS_VARIABLE) {
18796
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 stats->records = static_cast<ha_rows>(stat_info.get_n_rows());
18797 27 stats->data_file_length =
18798
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 static_cast<ulonglong>(stat_info.get_clustered_index_size()) *
18799
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 page_size.physical();
18800 27 stats->index_file_length =
18801
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 static_cast<ulonglong>(stat_info.get_sum_of_other_index_size()) *
18802
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 page_size.physical();
18803
18804
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 11 times.
27 if (stats->records == 0) {
18805 16 stats->mean_rec_length = 0;
18806 } else {
18807 11 stats->mean_rec_length =
18808 11 static_cast<ulong>(stats->data_file_length / stats->records);
18809 }
18810 }
18811
18812 27 return (true);
18813 35 }
18814
18815 3528 static bool innobase_get_table_statistics(
18816 const char *db_name, const char *table_name, dd::Object_id se_private_id,
18817 const dd::Properties &ts_se_private_data,
18818 const dd::Properties &tbl_se_private_data, uint stat_flags,
18819 ha_statistics *stats) {
18820 char norm_name[FN_REFLEN];
18821 dict_table_t *ib_table;
18822
18823 char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1];
18824 bool truncated;
18825
1/2
✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
3528 build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0,
18826 &truncated);
18827
18828
4/8
✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3528 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3528 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3528 times.
3528 if (truncated || !normalize_table_name(norm_name, buf)) {
18829 ut_d(ut_error);
18830 ut_o(return true); // (HA_ERR_TOO_LONG_PATH);
18831 }
18832
18833 3528 MDL_ticket *mdl = nullptr;
18834
1/2
✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
3528 THD *thd = current_thd;
18835
18836
1/2
✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
3528 ib_table = dd_table_open_on_name_in_mem(norm_name, false);
18837
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3493 times.
3528 if (ib_table == nullptr) {
18838
3/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 8 times.
35 if (innodb_get_table_statistics_for_uncached(
18839 db_name, table_name, norm_name, se_private_id, ts_se_private_data,
18840 tbl_se_private_data, stat_flags, stats)) {
18841 27 return (false);
18842 }
18843
18844 /** If the table doesn't have persistent stats then
18845 load the table from disk. */
18846
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false,
18847 DICT_ERR_IGNORE_NONE);
18848
18849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ib_table == nullptr) {
18850 return (true);
18851 }
18852 }
18853
18854
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 if (stat_flags & HA_STATUS_AUTO) {
18855
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 stats->auto_increment_value = innobase_peek_autoinc(ib_table, false);
18856 }
18857
18858
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 if (stat_flags & HA_STATUS_TIME) {
18859 3501 stats->update_time = static_cast<ulong>(
18860 3501 std::chrono::system_clock::to_time_t(ib_table->update_time.load()));
18861 }
18862
18863
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 if (stat_flags & HA_STATUS_VARIABLE_EXTRA) {
18864
2/4
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3501 times.
✗ Branch 3 not taken.
3501 calculate_delete_length_stat(ib_table, stats, current_thd);
18865 }
18866
18867
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 if (stat_flags & HA_STATUS_VARIABLE) {
18868
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 dict_stats_init(ib_table);
18869
18870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3501 times.
3501 ut_a(ib_table->stat_initialized);
18871
18872 /* Note it may look like ib_table->* arguments are
18873 redundant. If you see the usage of this call in info_low(),
18874 the stats can be retrieved while holding a latch if
18875 !HA_STATUS_NO_LOCK is passed. */
18876
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 calculate_index_size_stats(ib_table, ib_table->stat_n_rows,
18877 ib_table->stat_clustered_index_size,
18878 ib_table->stat_sum_of_other_index_sizes, stats);
18879 }
18880
18881
1/2
✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
3501 dd_table_close(ib_table, thd, &mdl, false);
18882
18883 3501 return (false);
18884 }
18885
18886 727 static bool innobase_get_index_column_cardinality(
18887 const char *db_name, const char *table_name, const char *index_name, uint,
18888 uint column_ordinal_position, dd::Object_id, ulonglong *cardinality) {
18889 char norm_name[FN_REFLEN];
18890 dict_table_t *ib_table;
18891 727 bool failure = true;
18892
18893 char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1];
18894 bool truncated;
18895
1/2
✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
727 build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0,
18896 &truncated);
18897
18898
4/8
✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 727 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 727 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 727 times.
727 if (truncated || !normalize_table_name(norm_name, buf)) {
18899 /* purecov: begin inspected */
18900 ut_d(ut_error);
18901 ut_o(return (true));
18902 /* purecov: end */
18903 }
18904
18905 727 MDL_ticket *mdl = nullptr;
18906
1/2
✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
727 THD *thd = current_thd;
18907
18908
1/2
✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
727 ib_table = dd_table_open_on_name_in_mem(norm_name, false);
18909
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 722 times.
727 if (ib_table == nullptr) {
18910
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if (row_search_index_stats(db_name, table_name, index_name,
18911 column_ordinal_position, cardinality)) {
18912 5 return (false);
18913 }
18914
18915 /** If the table doesn't have persistent stats then
18916 load the table from disk. */
18917 ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false,
18918 DICT_ERR_IGNORE_NONE);
18919
18920 if (ib_table == nullptr) {
18921 return (true);
18922 }
18923 }
18924
18925
2/4
✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 722 times.
722 if (ib_table->is_fts_aux()) {
18926 /* Server should not ask for Stats for Internal Tables */
18927 dd_table_close(ib_table, thd, &mdl, false);
18928 ut_d(ut_error);
18929 ut_o(return (true));
18930 }
18931
18932
5/10
✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 256 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 978 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 978 times.
✗ Branch 9 not taken.
978 for (const dict_index_t *index : ib_table->indexes) {
18933
6/8
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 978 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 722 times.
✓ Branch 5 taken 256 times.
✓ Branch 6 taken 722 times.
✓ Branch 7 taken 256 times.
978 if (index->is_committed() && ut_strcmp(index_name, index->name) == 0) {
18934
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 662 times.
722 if (ib_table->stat_initialized == 0) {
18935
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 dict_stats_init(ib_table);
18936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 ut_a(ib_table->stat_initialized != 0);
18937 }
18938
18939
2/4
✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
722 DEBUG_SYNC(thd, "innodb.after_init_check");
18940
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 707 times.
722 if (index->type & (DICT_FTS | DICT_SPATIAL)) {
18941 /* For these indexes innodb_rec_per_key is
18942 fixed as 1.0 */
18943 15 *cardinality = ib_table->stat_n_rows;
18944 } else {
18945 707 uint64_t n_rows = ib_table->stat_n_rows;
18946 double records =
18947 1414 (n_rows /
18948
1/2
✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
707 innodb_rec_per_key(index, (ulint)column_ordinal_position, n_rows));
18949 707 *cardinality = static_cast<ulonglong>(round(records));
18950 }
18951
18952 722 failure = false;
18953 722 break;
18954 }
18955 }
18956
18957
1/2
✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
722 dd_table_close(ib_table, thd, &mdl, false);
18958 722 return (failure);
18959 }
18960
18961 858 static bool innobase_is_tablespace_keyring_pre_v3_encrypted(
18962 const dd::Tablespace &tablespace, int &error) {
18963 858 error = 0;
18964 858 space_id_t id = 0;
18965
18966
3/6
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 858 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 858 times.
858 ut_ad(innobase_strcasecmp(tablespace.engine().c_str(), "InnoDB") == 0);
18967
18968
4/8
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 858 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 858 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 858 times.
858 if (tablespace.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id))
18969 return true;
18970
18971 /* Make sure tablespace is loaded. */
18972
1/2
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
858 fil_space_t *space = fil_space_get(id);
18973
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 849 times.
858 if (space == nullptr) {
18974 9 error = HA_ERR_TABLESPACE_MISSING;
18975 9 return false;
18976 }
18977
18978 // If page0 was read and it has crypt - we can check if it is encrypted here
18979 // if crypt_data is null it means that page0 may not have yet been read - we
18980 // will read it in fil_space_open_if_needed and recheck if crypt_data is null
18981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 849 times.
849 if (space->crypt_data != nullptr)
18982 return is_space_keyring_pre_v3_encrypted(space);
18983
18984
1/2
✓ Branch 0 taken 849 times.
✗ Branch 1 not taken.
849 fil_space_open_if_needed(space);
18985
18986 // We do not need to care about mutexes as this function is only called during
18987 // the upgrade
18988
1/2
✓ Branch 0 taken 849 times.
✗ Branch 1 not taken.
849 return is_space_keyring_pre_v3_encrypted(space);
18989 }
18990
18991 476515 static bool innobase_get_tablespace_type(const dd::Tablespace &space,
18992 Tablespace_type *space_type) {
18993 476515 space_id_t id = 0;
18994 476515 uint32_t flags = 0;
18995
18996
3/6
✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476515 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 476515 times.
476515 ut_ad(innobase_strcasecmp(space.engine().c_str(), "InnoDB") == 0);
18997
18998
5/12
✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476515 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 476515 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 476515 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 476515 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1429545 if (space.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id) ||
18999
6/14
✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476515 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 476515 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 476515 times.
✓ Branch 8 taken 476515 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 476515 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
953030 space.se_private_data().get(dd_space_key_strings[DD_SPACE_FLAGS],
19000 &flags)) {
19001 return true;
19002 }
19003
19004
5/6
✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56176 times.
✓ Branch 3 taken 420339 times.
✓ Branch 4 taken 56176 times.
✓ Branch 5 taken 420339 times.
532691 if (space.id() == MYSQL_TABLESPACE_DD_ID &&
19005
1/2
✓ Branch 0 taken 56176 times.
✗ Branch 1 not taken.
56176 id == dict_sys_t::s_dict_space_id) {
19006 56176 *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY;
19007
2/2
✓ Branch 0 taken 737 times.
✓ Branch 1 taken 419602 times.
420339 } else if (id == TRX_SYS_SPACE) {
19008 737 *space_type = Tablespace_type::SPACE_TYPE_SYSTEM;
19009
3/4
✓ Branch 0 taken 419602 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 419567 times.
419602 } else if (fsp_is_undo_tablespace(id)) {
19010 35 *space_type = Tablespace_type::SPACE_TYPE_UNDO;
19011
3/4
✓ Branch 0 taken 419567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 419550 times.
419567 } else if (fsp_is_system_temporary(id)) {
19012 17 *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY;
19013
6/8
✓ Branch 0 taken 409064 times.
✓ Branch 1 taken 10486 times.
✓ Branch 2 taken 409064 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 409064 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 409064 times.
✓ Branch 7 taken 10486 times.
419550 } else if (fsp_is_shared_tablespace(flags) && fsp_is_ibd_tablespace(id)) {
19014 409064 *space_type = Tablespace_type::SPACE_TYPE_SHARED;
19015
2/4
✓ Branch 0 taken 10486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10486 times.
✗ Branch 3 not taken.
10486 } else if (fsp_is_file_per_table(id, flags)) {
19016 10486 *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT;
19017 } else {
19018 ut_d(ut_error);
19019 ut_o(return true);
19020 }
19021
19022 476515 return false;
19023 }
19024
19025 /** Get the tablespace type given the name.
19026
19027 @param[in] tablespace_name tablespace name
19028 @param[out] space_type type of space
19029
19030 @return Operation status.
19031 @retval false on success and true for failure.
19032 */
19033 1175855 static bool innobase_get_tablespace_type_by_name(const char *tablespace_name,
19034 Tablespace_type *space_type) {
19035
6/6
✓ Branch 0 taken 267370 times.
✓ Branch 1 taken 908485 times.
✓ Branch 2 taken 864 times.
✓ Branch 3 taken 266506 times.
✓ Branch 4 taken 908488 times.
✓ Branch 5 taken 861 times.
1175855 if ((tablespace_name == nullptr && srv_file_per_table) ||
19036 908488 (tablespace_name &&
19037
2/2
✓ Branch 0 taken 1234 times.
✓ Branch 1 taken 907254 times.
908488 0 == strcmp(tablespace_name, dict_sys_t::s_file_per_table_name))) {
19038 267740 *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT;
19039
4/6
✓ Branch 0 taken 864 times.
✓ Branch 1 taken 907251 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 864 times.
✓ Branch 4 taken 907264 times.
✗ Branch 5 not taken.
908115 } else if ((tablespace_name == nullptr && !srv_file_per_table) ||
19040 907264 (tablespace_name &&
19041
2/2
✓ Branch 0 taken 1117 times.
✓ Branch 1 taken 906147 times.
907264 0 == strcmp(tablespace_name, dict_sys_t::s_sys_space_name))) {
19042 1981 *space_type = Tablespace_type::SPACE_TYPE_SYSTEM;
19043
2/2
✓ Branch 0 taken 902547 times.
✓ Branch 1 taken 3587 times.
906134 } else if (0 == strcmp(tablespace_name, dict_sys_t::s_dd_space_name)) {
19044 902547 *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY;
19045
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3579 times.
3587 } else if (0 == strcmp(tablespace_name, dict_sys_t::s_temp_space_name)) {
19046 8 *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY;
19047
1/2
✓ Branch 0 taken 3592 times.
✗ Branch 1 not taken.
3579 } else if (0 == strcmp(tablespace_name,
19048 3592 dict_sys_t::s_default_undo_space_name_1) ||
19049
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3592 times.
3592 0 == strcmp(tablespace_name,
19050 dict_sys_t::s_default_undo_space_name_2)) {
19051 /*
19052 TODO: This function doesn't consider user created UNDO
19053 tablespaces because, as of now this function is not being
19054 called for UNDO tablesapces. But should consider this in
19055 future for completeness.
19056 */
19057 *space_type = Tablespace_type::SPACE_TYPE_UNDO;
19058 } else {
19059 3592 *space_type = Tablespace_type::SPACE_TYPE_SHARED;
19060 }
19061
19062 1175855 return false;
19063 }
19064
19065 281326 static bool innobase_get_tablespace_statistics(
19066 const char *tablespace_name, const char *file_name,
19067 const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats) {
19068 /* Tablespace does not have space id stored. */
19069
3/6
✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 281326 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 281326 times.
281326 if (!ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID])) {
19070 my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name);
19071 return (DD_FAILURE);
19072 }
19073
19074 space_id_t space_id;
19075
19076
2/4
✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 281326 times.
✗ Branch 3 not taken.
281326 ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id);
19077
19078
3/4
✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56482 times.
✓ Branch 3 taken 224844 times.
281326 if (fsp_is_undo_tablespace(space_id)) {
19079 /* Get the ddl_mutex so that if an undo truncation is happening by
19080 the purge thread, it will complete before we continue. */
19081
1/2
✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
56482 mutex_enter(&undo::ddl_mutex);
19082
19083 /* When selecting information_schema.files, no MVCC is used. So it is
19084 possible to read an uncommitted DD record that indicates the undo
19085 space is empty and shows the new space_id after a truncation.
19086 Adjust for that possibility by always using the current space_id. */
19087
1/2
✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
56482 undo::spaces->s_lock();
19088 56482 space_id_t undo_num = undo::id2num(space_id);
19089
1/2
✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
56482 undo::Tablespace *undo_space = undo::spaces->find(undo_num);
19090
2/2
✓ Branch 0 taken 56475 times.
✓ Branch 1 taken 7 times.
56482 if (undo_space != nullptr) {
19091 56475 space_id = undo_space->id();
19092 }
19093
1/2
✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
56482 undo::spaces->s_unlock();
19094 }
19095
19096
1/2
✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
281326 auto space = fil_space_acquire(space_id);
19097
19098 /* Tablespace is missing in this case. */
19099
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 281287 times.
281326 if (space == nullptr) {
19100
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name);
19101
3/4
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 32 times.
39 if (fsp_is_undo_tablespace(space_id)) {
19102
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mutex_exit(&undo::ddl_mutex);
19103 }
19104 39 return (DD_FAILURE);
19105 }
19106
19107 281287 stats->m_id = space->id;
19108
19109 281287 const char *type = "TABLESPACE";
19110
19111 281287 fil_type_t purpose = space->purpose;
19112
19113
2/4
✓ Branch 0 taken 253360 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27927 times.
✗ Branch 3 not taken.
281287 switch (purpose) {
19114 253360 case FIL_TYPE_TABLESPACE:
19115
3/4
✓ Branch 0 taken 253360 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56475 times.
✓ Branch 3 taken 196885 times.
253360 if (fsp_is_undo_tablespace(space_id)) {
19116 56475 type = "UNDO LOG";
19117 56475 break;
19118 } /* else fall through for TABLESPACE */
19119 case FIL_TYPE_IMPORT:
19120 /* 'IMPORTING'is a status. The type is TABLESPACE. */
19121 196885 break;
19122 27927 case FIL_TYPE_TEMPORARY:
19123 27927 type = "TEMPORARY";
19124 27927 break;
19125 }
19126
19127
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 stats->m_type = type;
19128
19129 281287 stats->m_free_extents = space->free_len;
19130
19131
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 page_size_t page_size{space->flags};
19132
19133
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 page_no_t extent_pages = fsp_get_extent_size_in_pages(page_size);
19134
19135 281287 stats->m_total_extents = space->size_in_header / extent_pages;
19136
19137
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 stats->m_extent_size = extent_pages * page_size.physical();
19138
19139 281287 const fil_node_t *file = nullptr;
19140
19141 /* Use only the basename when searching for system tablespaces since
19142 InnoDB places them in innodb_data_home_dir and the DD may only know
19143 the basename. Since they are open, they are in the right place. */
19144 std::string search_name =
19145
2/2
✓ Branch 0 taken 27927 times.
✓ Branch 1 taken 225425 times.
253352 (space->id == TRX_SYS_SPACE || space->id == dict_sys_t::s_temp_space_id)
19146 281287 ? Fil_path::get_basename(file_name)
19147
11/20
✓ Branch 0 taken 253352 times.
✓ Branch 1 taken 27935 times.
✓ Branch 2 taken 55862 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 55862 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 225425 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 225425 times.
✓ Branch 9 taken 55862 times.
✓ Branch 10 taken 55862 times.
✓ Branch 11 taken 225425 times.
✓ Branch 12 taken 55862 times.
✓ Branch 13 taken 225425 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
1153075 : file_name;
19148
19149 /* Normalize the file name to search for. */
19150 281287 Fil_path::normalize(search_name);
19151
19152 /* Find the fil_node_t that matches the filename. */
19153
1/2
✓ Branch 0 taken 281303 times.
✗ Branch 1 not taken.
281303 for (const auto &f : space->files) {
19154
4/6
✓ Branch 0 taken 281303 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 281303 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 281283 times.
✓ Branch 5 taken 20 times.
281303 if (Fil_path::is_same_as(search_name, f.name)) {
19155 281283 file = &f;
19156 281283 break;
19157 }
19158
19159 /* Try to compare only the basename. */
19160
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (space->id == TRX_SYS_SPACE ||
19161
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 space->id == dict_sys_t::s_temp_space_id) {
19162
5/8
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 16 times.
20 if (Fil_path::is_same_as(search_name, Fil_path::get_basename(f.name))) {
19163 4 file = &f;
19164 4 break;
19165 }
19166 }
19167
19168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (space->files.size() == 1) {
19169 file = &f;
19170
19171 ib::info(ER_IB_MSG_570)
19172 << "Tablespace '" << tablespace_name << "'with DD filename '"
19173 << file_name << "' doesn't match the InnoDB filename '" << f.name
19174 << "'";
19175 }
19176 }
19177
19178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281287 times.
281287 if (file == nullptr) {
19179 ib::warn(ER_IB_MSG_571) << "Tablespace '" << tablespace_name << "'"
19180 << " filename is unknown. Use --innodb-directories"
19181 << " to tell InnoDB the location of the file.";
19182
19183 my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name);
19184
19185 if (fsp_is_undo_tablespace(space_id)) {
19186 mutex_exit(&undo::ddl_mutex);
19187 }
19188
19189 return (DD_FAILURE);
19190 }
19191
19192
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 stats->m_initial_size = file->init_size * page_size.physical();
19193
19194 /** Store maximum size */
19195
2/2
✓ Branch 0 taken 281275 times.
✓ Branch 1 taken 12 times.
281287 if (file->max_size >= PAGE_NO_MAX) {
19196 281275 stats->m_maximum_size = ~0ULL;
19197 } else {
19198
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 stats->m_maximum_size = file->max_size * page_size.physical();
19199 }
19200
19201 /** Store autoextend size */
19202 page_no_t extend_pages;
19203
19204
2/2
✓ Branch 0 taken 27935 times.
✓ Branch 1 taken 253352 times.
281287 if (space->id == TRX_SYS_SPACE) {
19205
1/2
✓ Branch 0 taken 27935 times.
✗ Branch 1 not taken.
27935 extend_pages = srv_sys_space.get_increment();
19206
19207
3/4
✓ Branch 0 taken 253352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27927 times.
✓ Branch 3 taken 225425 times.
253352 } else if (fsp_is_system_temporary(space->id)) {
19208
1/2
✓ Branch 0 taken 27927 times.
✗ Branch 1 not taken.
27927 extend_pages = srv_tmp_space.get_increment();
19209
19210
3/4
✓ Branch 0 taken 225425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56475 times.
✓ Branch 3 taken 168950 times.
225425 } else if (fsp_is_undo_tablespace(space->id)) {
19211 56475 extend_pages = space->m_undo_extend;
19212
19213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168950 times.
168950 } else if (space->autoextend_size_in_bytes > 0) {
19214 extend_pages = space->autoextend_size_in_bytes / page_size.physical();
19215 } else {
19216
1/2
✓ Branch 0 taken 168950 times.
✗ Branch 1 not taken.
168950 extend_pages = fsp_get_pages_to_extend_ibd(page_size, file->size);
19217 }
19218
19219
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 stats->m_autoextend_size = extend_pages * page_size.physical();
19220
19221
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 auto avail_space = fsp_get_available_space_in_free_extents(space);
19222
19223 281287 stats->m_data_free = avail_space * 1024;
19224
19225
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 281287 times.
✓ Branch 2 taken 281287 times.
✗ Branch 3 not taken.
281287 stats->m_status = (purpose == FIL_TYPE_IMPORT ? "IMPORTING" : "NORMAL");
19226
19227
1/2
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
281287 fil_space_release(space);
19228
19229
3/4
✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56475 times.
✓ Branch 3 taken 224812 times.
281287 if (fsp_is_undo_tablespace(space_id)) {
19230
1/2
✓ Branch 0 taken 56475 times.
✗ Branch 1 not taken.
56475 mutex_exit(&undo::ddl_mutex);
19231 }
19232
19233 281287 return (DD_SUCCESS);
19234 }
19235
19236 /** Enable indexes.
19237 @param[in] mode enable index mode.
19238 @return HA_ERR_* error code or 0 */
19239 504 int ha_innobase::enable_indexes(uint mode) {
19240 504 int error = HA_ERR_WRONG_COMMAND;
19241
19242 /* Enable index only for intrinsic table. Behavior for all other
19243 table continue to remain same. */
19244
19245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 if (m_prebuilt->table->is_intrinsic()) {
19246 ut_ad(mode == HA_KEY_SWITCH_ALL);
19247 for (auto index : m_prebuilt->table->indexes) {
19248 /* InnoDB being clustered index we can't disable/enable
19249 clustered index itself. */
19250 if (index->is_clustered()) {
19251 continue;
19252 }
19253
19254 index->allow_duplicates = false;
19255 }
19256 error = 0;
19257 }
19258
19259 504 return (error);
19260 }
19261
19262 /** Disable indexes.
19263 @param[in] mode disable index mode.
19264 @return HA_ERR_* error code or 0 */
19265 496 int ha_innobase::disable_indexes(uint mode) {
19266 496 int error = HA_ERR_WRONG_COMMAND;
19267
19268 /* Disable index only for intrinsic table. Behavior for all other
19269 table continue to remain same. */
19270
19271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
496 if (m_prebuilt->table->is_intrinsic()) {
19272 ut_ad(mode == HA_KEY_SWITCH_ALL);
19273 for (auto index : m_prebuilt->table->indexes) {
19274 /* InnoDB being clustered index we can't disable/enable
19275 clustered index itself. */
19276 if (index->is_clustered()) {
19277 continue;
19278 }
19279
19280 index->allow_duplicates = true;
19281 }
19282 error = 0;
19283 }
19284
19285 496 return (error);
19286 }
19287
19288 /**
19289 Updates index cardinalities of the table, based on random dives into
19290 each index tree. This does NOT calculate exact statistics on the table.
19291 @return HA_ADMIN_* error code or HA_ADMIN_OK */
19292
19293 5908 int ha_innobase::analyze(THD *, /*!< in: connection thread handle */
19294 HA_CHECK_OPT *) /*!< in: currently ignored */
19295 {
19296
5/10
✓ Branch 0 taken 5524 times.
✓ Branch 1 taken 384 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5524 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5908 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5908 times.
5908 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
19297 m_share->ib_table->is_corrupt)) {
19298 return (HA_ADMIN_CORRUPT);
19299 }
19300
19301 /* Simply call info_low() with all the flags
19302 and request recalculation of the statistics */
19303 5908 int ret = info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
19304 true /* this is ANALYZE */);
19305
19306
5/10
✓ Branch 0 taken 5524 times.
✓ Branch 1 taken 384 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5524 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5908 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5908 times.
5908 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
19307 m_share->ib_table->is_corrupt)) {
19308 return (HA_ADMIN_CORRUPT);
19309 }
19310
19311
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5903 times.
5908 if (ret != 0) {
19312 5 return (HA_ADMIN_FAILED);
19313 }
19314
19315 5903 return (HA_ADMIN_OK);
19316 }
19317
19318 /** This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds
19319 the table in MySQL. */
19320
19321 2023 int ha_innobase::optimize(THD *, /*!< in: connection thread handle */
19322 HA_CHECK_OPT *) /*!< in: currently ignored */
19323 {
19324
1/2
✓ Branch 0 taken 2023 times.
✗ Branch 1 not taken.
2023 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
19325
19326 /* FTS-FIXME: Since MySQL doesn't support engine-specific commands,
19327 we have to hijack some existing command in order to be able to test
19328 the new admin commands added in InnoDB's FTS support. For now, we
19329 use MySQL's OPTIMIZE command, normally mapped to ALTER TABLE in
19330 InnoDB (so it recreates the table anew), and map it to OPTIMIZE.
19331
19332 This works OK otherwise, but MySQL locks the entire table during
19333 calls to OPTIMIZE, which is undesirable. */
19334
19335
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2015 times.
2023 if (innodb_optimize_fulltext_only) {
19336
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
16 if (m_prebuilt->table->fts && m_prebuilt->table->fts->cache &&
19337
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 !dict_table_is_discarded(m_prebuilt->table)) {
19338
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 fts_sync_table(m_prebuilt->table, false, true, false);
19339
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 fts_optimize_table(m_prebuilt->table);
19340 }
19341 8 return (HA_ADMIN_OK);
19342 } else {
19343 2015 return (HA_ADMIN_TRY_ALTER);
19344 }
19345 2023 }
19346
19347 /** Tries to check that an InnoDB table is not corrupted. If corruption is
19348 noticed, prints to stderr information about it. In case of corruption
19349 may also assert a failure and crash the server.
19350 @return HA_ADMIN_CORRUPT or HA_ADMIN_OK */
19351
19352 3941 int ha_innobase::check(THD *thd, /*!< in: user thread handle */
19353 HA_CHECK_OPT *check_opt) /*!< in: check options */
19354 {
19355 dict_index_t *index;
19356 ulint n_rows;
19357 3941 ulint n_rows_in_table = ULINT_UNDEFINED;
19358 3941 ulint n_dups = 0;
19359 3941 bool is_ok = true;
19360 ulint old_isolation_level;
19361 dberr_t ret;
19362
19363
1/2
✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
3941 DBUG_TRACE;
19364
2/4
✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3941 times.
3941 assert(thd == ha_thd());
19365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3941 times.
3941 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
19366
2/4
✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3941 times.
3941 ut_a(m_prebuilt->trx == thd_to_trx(thd));
19367
19368
1/2
✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
3941 TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
19369
19370
2/2
✓ Branch 0 taken 1261 times.
✓ Branch 1 taken 2680 times.
3941 if (m_prebuilt->mysql_template == nullptr) {
19371 /* Build the template; we will use a dummy template
19372 in index scans done in checking */
19373
19374
1/2
✓ Branch 0 taken 1261 times.
✗ Branch 1 not taken.
1261 build_template(true);
19375 }
19376
19377
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3937 times.
3941 if (dict_table_is_discarded(m_prebuilt->table)) {
19378 4 ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED,
19379
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 table->s->table_name.str);
19380
19381 4 return HA_ADMIN_CORRUPT;
19382
19383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3937 times.
3937 } else if (m_prebuilt->table->ibd_file_missing) {
19384 ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING,
19385 table->s->table_name.str);
19386
19387 return HA_ADMIN_CORRUPT;
19388 }
19389
19390 3937 m_prebuilt->trx->op_info = "checking table";
19391
19392
2/4
✓ Branch 0 taken 3937 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3937 times.
3937 if (m_prebuilt->table->is_corrupted()) {
19393 /* Now that the table is already marked as corrupted,
19394 there is no need to check any index of this table */
19395 m_prebuilt->trx->op_info = "";
19396 if (thd_killed(m_user_thd)) {
19397 thd_set_kill_status(m_user_thd);
19398 }
19399
19400 return HA_ADMIN_CORRUPT;
19401 }
19402
19403 3937 old_isolation_level = m_prebuilt->trx->isolation_level;
19404
19405 /* We must run the index record counts at an isolation level
19406 >= READ COMMITTED, because a dirty read can see a wrong number
19407 of records in some index; to play safe, we use always
19408 REPEATABLE READ here */
19409 3937 m_prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
19410
19411
2/4
✓ Branch 0 taken 3937 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3937 times.
3937 ut_ad(!m_prebuilt->table->is_corrupted());
19412
19413
3/4
✓ Branch 0 taken 3937 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6642 times.
✓ Branch 3 taken 3934 times.
10576 for (index = m_prebuilt->table->first_index(); index != nullptr;
19414
1/2
✓ Branch 0 taken 6639 times.
✗ Branch 1 not taken.
6639 index = index->next()) {
19415 /* If this is an index being created or dropped, skip */
19416
3/4
✓ Branch 0 taken 6642 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6640 times.
6642 if (!index->is_committed()) {
19417 2 continue;
19418 }
19419
19420
6/8
✓ Branch 0 taken 6640 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6640 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6623 times.
✓ Branch 5 taken 17 times.
✓ Branch 6 taken 6623 times.
✓ Branch 7 taken 17 times.
6640 if (!(check_opt->flags & T_QUICK) && !index->is_corrupted()) {
19421 /* Enlarge the fatal lock wait timeout during
19422 CHECK TABLE. */
19423 srv_fatal_semaphore_wait_extend.fetch_add(1);
19424
19425
1/2
✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
6623 bool valid = btr_validate_index(index, m_prebuilt->trx, false);
19426
19427 /* Restore the fatal lock wait timeout after
19428 CHECK TABLE. */
19429 srv_fatal_semaphore_wait_extend.fetch_sub(1);
19430
19431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6623 times.
6623 if (!valid) {
19432 is_ok = false;
19433
19434 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
19435 "InnoDB: The B-tree of"
19436 " index %s is corrupted.",
19437 index->name());
19438 continue;
19439 }
19440 }
19441
19442 /* Instead of invoking change_active_index(), set up
19443 a dummy template for non-locking reads, disabling
19444 access to the clustered index. */
19445 6640 m_prebuilt->index = index;
19446
19447
1/2
✓ Branch 0 taken 6640 times.
✗ Branch 1 not taken.
6640 m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx);
19448
19449
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 6623 times.
6640 if (!m_prebuilt->index_usable) {
19450
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 if (m_prebuilt->index->is_corrupted()) {
19451
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 push_warning_printf(m_user_thd, Sql_condition::SL_WARNING,
19452 HA_ERR_INDEX_CORRUPT,
19453 "InnoDB: Index %s is marked as"
19454 " corrupted",
19455 index->name());
19456 17 is_ok = false;
19457 } else {
19458 push_warning_printf(thd, Sql_condition::SL_WARNING,
19459 HA_ERR_TABLE_DEF_CHANGED,
19460 "InnoDB: Insufficient history for"
19461 " index %s",
19462 index->name());
19463 }
19464 17 continue;
19465 }
19466
19467 6623 m_prebuilt->sql_stat_start = true;
19468 6623 m_prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
19469 6623 m_prebuilt->n_template = 0;
19470 6623 m_prebuilt->need_to_access_clustered = false;
19471
19472
1/2
✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
6623 m_prebuilt->clear_search_tuples();
19473
19474 6623 m_prebuilt->select_lock_type = LOCK_NONE;
19475
19476
1/2
✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
6623 size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd);
19477
19478 /* Scan this index. */
19479
3/4
✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 6575 times.
6623 if (dict_index_is_spatial(index)) {
19480
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 ret = row_count_rtree_recs(m_prebuilt, &n_rows, &n_dups);
19481 } else {
19482
1/2
✓ Branch 0 taken 6574 times.
✗ Branch 1 not taken.
6575 ret = row_scan_index_for_mysql(m_prebuilt, index, max_threads, true,
19483 &n_rows);
19484 }
19485
19486
5/8
✓ Branch 0 taken 6622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6620 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
6622 DBUG_EXECUTE_IF(
19487 "dict_set_clust_index_corrupted",
19488 if (index->is_clustered()) { ret = DB_CORRUPTION; });
19489
19490
6/8
✓ Branch 0 taken 6622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 6605 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 6 times.
6622 DBUG_EXECUTE_IF(
19491 "dict_set_index_corrupted",
19492 if (!index->is_clustered()) { ret = DB_CORRUPTION; });
19493
19494
4/8
✓ Branch 0 taken 6622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6622 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6622 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6622 times.
6622 if (ret == DB_INTERRUPTED || thd_killed(m_user_thd)) {
19495 /* Do not report error since this could happen
19496 during shutdown */
19497 break;
19498 }
19499
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6609 times.
6622 if (ret != DB_SUCCESS) {
19500 /* Assume some kind of corruption. */
19501
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
19502 "InnoDB: The B-tree of"
19503 " index %s is corrupted.",
19504 index->name());
19505 13 is_ok = false;
19506
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
13 dict_set_corrupted(index);
19507 }
19508
19509
3/4
✓ Branch 0 taken 6620 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3936 times.
✓ Branch 3 taken 2684 times.
6620 if (index == m_prebuilt->table->first_index()) {
19510 3936 n_rows_in_table = n_rows;
19511
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 2600 times.
2641 } else if (!(index->type & DICT_FTS) && (n_rows != n_rows_in_table) &&
19512
5/8
✓ Branch 0 taken 2641 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2684 times.
5325 (!index->is_multi_value()) &&
19513 (!dict_index_is_spatial(index) || (n_rows < n_rows_in_table) ||
19514 (n_dups < n_rows - n_rows_in_table))) {
19515 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
19516 "InnoDB: Index '%-.200s' contains %lu"
19517 " entries, should be %lu.",
19518 index->name(), (ulong)n_rows, (ulong)n_rows_in_table);
19519 is_ok = false;
19520 dict_set_corrupted(index);
19521 }
19522 }
19523
19524 /* Restore the original isolation level */
19525 3934 m_prebuilt->trx->isolation_level =
19526 3934 static_cast<trx_t::isolation_level_t>(old_isolation_level);
19527
19528 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
19529 /* We validate the whole adaptive hash index for all tables
19530 at every CHECK TABLE only when QUICK flag is not present. */
19531
19532
4/8
✓ Branch 0 taken 3934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3934 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3934 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3934 times.
3934 if (!(check_opt->flags & T_QUICK) && !btr_search_validate()) {
19533 push_warning(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE,
19534 "InnoDB: The adaptive hash index is corrupted.");
19535 is_ok = false;
19536 }
19537 #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
19538 3934 m_prebuilt->trx->op_info = "";
19539
2/4
✓ Branch 0 taken 3934 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3934 times.
3934 if (thd_killed(m_user_thd)) {
19540 thd_set_kill_status(m_user_thd);
19541 }
19542
19543
5/10
✓ Branch 0 taken 946 times.
✓ Branch 1 taken 2988 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 946 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3934 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3934 times.
3934 if (UNIV_UNLIKELY(m_share && m_share->ib_table &&
19544 m_share->ib_table->is_corrupt)) {
19545 return HA_ADMIN_CORRUPT;
19546 }
19547
19548
2/2
✓ Branch 0 taken 3918 times.
✓ Branch 1 taken 16 times.
3934 return is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT;
19549 3938 }
19550
19551 /** Tells something additional to the handler about how to do things.
19552 @return 0 or error number */
19553
19554 1004099314 int ha_innobase::extra(enum ha_extra_function operation)
19555 /*!< in: HA_EXTRA_FLUSH or some other flag */
19556 {
19557
1/2
✓ Branch 0 taken 1004100936 times.
✗ Branch 1 not taken.
1004099314 if (m_prebuilt->table) {
19558 #ifdef UNIV_DEBUG
19559
2/2
✓ Branch 0 taken 1004100323 times.
✓ Branch 1 taken 28 times.
1004100936 if (m_prebuilt->table->n_ref_count > 0)
19560 #endif /* UNIV_DEBUG */
19561 1004100323 update_thd();
19562 }
19563
19564 /* Warning: since it is not sure that MySQL calls external_lock
19565 before calling this function, the trx field in m_prebuilt can be
19566 obsolete! */
19567
19568
13/14
✗ Branch 0 not taken.
✓ Branch 1 taken 108106047 times.
✓ Branch 2 taken 1225838 times.
✓ Branch 3 taken 1256145 times.
✓ Branch 4 taken 199018 times.
✓ Branch 5 taken 82637 times.
✓ Branch 6 taken 114538976 times.
✓ Branch 7 taken 2272419 times.
✓ Branch 8 taken 114539324 times.
✓ Branch 9 taken 2364461 times.
✓ Branch 10 taken 7725 times.
✓ Branch 11 taken 7723 times.
✓ Branch 12 taken 95101930 times.
✓ Branch 13 taken 564398572 times.
1004100815 switch (operation) {
19569 case HA_EXTRA_FLUSH:
19570 if (m_prebuilt->blob_heap) {
19571 row_mysql_prebuilt_free_blob_heap(m_prebuilt);
19572 }
19573
19574 if (m_prebuilt->compress_heap) {
19575 row_mysql_prebuilt_free_compress_heap(m_prebuilt);
19576 }
19577
19578 break;
19579 108106047 case HA_EXTRA_RESET_STATE:
19580 108106047 reset_template();
19581 108105989 m_prebuilt->replace = 0;
19582 108105989 m_prebuilt->on_duplicate_key_update = 0;
19583 108105989 break;
19584 1225838 case HA_EXTRA_NO_KEYREAD:
19585 1225838 m_prebuilt->read_just_key = 0;
19586 1225838 break;
19587 1256145 case HA_EXTRA_KEYREAD:
19588 1256145 m_prebuilt->read_just_key = 1;
19589 1256145 break;
19590 199018 case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
19591 199018 m_prebuilt->keep_other_fields_on_keyread = 1;
19592 199018 break;
19593
19594 /* IMPORTANT: m_prebuilt->trx can be obsolete in
19595 this method, because it is not sure that MySQL
19596 calls external_lock before this method with the
19597 parameters below. We must not invoke update_thd()
19598 either, because the calling threads may change.
19599 CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
19600 82637 case HA_EXTRA_INSERT_WITH_UPDATE:
19601 82637 m_prebuilt->on_duplicate_key_update = 1;
19602 82637 break;
19603 114538976 case HA_EXTRA_NO_IGNORE_DUP_KEY:
19604 114538976 m_prebuilt->on_duplicate_key_update = 0;
19605 114538976 break;
19606 2272419 case HA_EXTRA_WRITE_CAN_REPLACE:
19607 2272419 m_prebuilt->replace = 1;
19608 2272419 break;
19609 114539324 case HA_EXTRA_WRITE_CANNOT_REPLACE:
19610 114539324 m_prebuilt->replace = 0;
19611 114539324 break;
19612 2364461 case HA_EXTRA_NO_READ_LOCKING:
19613 2364461 m_prebuilt->no_read_locking = true;
19614 2364461 break;
19615 7725 case HA_EXTRA_BEGIN_ALTER_COPY:
19616 7725 m_prebuilt->table->skip_alter_undo = 1;
19617 7725 break;
19618 7723 case HA_EXTRA_END_ALTER_COPY:
19619 7723 m_prebuilt->table->skip_alter_undo = 0;
19620 7723 break;
19621 95101930 case HA_EXTRA_NO_AUTOINC_LOCKING:
19622 95101930 m_prebuilt->no_autoinc_locking = true;
19623 95101930 break;
19624 1004100757 default: /* Do nothing */
19625 ;
19626 }
19627
19628 1004100757 return (0);
19629 }
19630
19631 /**
19632 MySQL calls this method at the end of each statement. This method
19633 exists for readability only. ha_innobase::reset() doesn't give any
19634 clue about the method. */
19635
19636 114538733 int ha_innobase::end_stmt() {
19637
2/2
✓ Branch 0 taken 12352459 times.
✓ Branch 1 taken 102186274 times.
114538733 if (m_prebuilt->blob_heap) {
19638 12352459 row_mysql_prebuilt_free_blob_heap(m_prebuilt);
19639 }
19640
19641
2/2
✓ Branch 0 taken 3187 times.
✓ Branch 1 taken 114535565 times.
114538752 if (m_prebuilt->compress_heap) {
19642 3187 row_mysql_prebuilt_free_compress_heap(m_prebuilt);
19643 }
19644
19645 114538752 m_prebuilt->end_stmt();
19646
19647 114538617 reset_template();
19648
19649 114539170 m_ds_mrr.reset();
19650
19651 /* TODO: This should really be reset in reset_template() but for now
19652 it's safer to do it explicitly here. */
19653
19654 /* This is a statement level counter. */
19655 114539152 m_prebuilt->autoinc_last_value = 0;
19656
19657 114539152 m_prebuilt->no_read_locking = false;
19658 114539152 m_prebuilt->no_autoinc_locking = false;
19659
19660 /* This transaction had called ha_innobase::start_stmt() */
19661 114539152 trx_t *trx = m_prebuilt->trx;
19662
19663
4/6
✓ Branch 0 taken 114292999 times.
✓ Branch 1 taken 246155 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114292805 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 114538960 times.
114539152 if (!m_prebuilt->table->is_temporary() && trx != thd_to_trx(ha_thd())) {
19664 ut_d(ut_error);
19665 ut_o(return (0));
19666 }
19667
19668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114539034 times.
114538960 ut_ad(!m_prebuilt->replace);
19669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114539074 times.
114539034 ut_ad(!m_prebuilt->on_duplicate_key_update);
19670
19671
2/2
✓ Branch 0 taken 2347621 times.
✓ Branch 1 taken 112191453 times.
114539074 if (trx->lock.start_stmt) {
19672 2347621 trx->lock.start_stmt = false;
19673 2347621 TrxInInnoDB::end_stmt(trx);
19674 }
19675
19676 114539133 return (0);
19677 }
19678
19679 /**
19680 MySQL calls this method at the end of each statement */
19681
19682 114538493 int ha_innobase::reset() { return (end_stmt()); }
19683
19684 /** MySQL calls this function at the start of each SQL statement inside LOCK
19685 TABLES. Inside LOCK TABLES the "::external_lock" method does not work to mark
19686 SQL statement borders. Note also a special case: if a temporary table is
19687 created inside LOCK TABLES, MySQL has not called external_lock() at all on
19688 that table.
19689 MySQL-5.0 also calls this before each statement in an execution of a stored
19690 procedure. To make the execution more deterministic for binlogging, MySQL-5.0
19691 locks all tables involved in a stored procedure with full explicit table locks
19692 (thd_in_lock_tables(thd) holds in store_lock()) before executing the procedure.
19693 @param[in] thd handle to the user thread
19694 @param[in] lock_type lock type
19695 @return 0 or error code */
19696 2416600 int ha_innobase::start_stmt(THD *thd, thr_lock_type lock_type) {
19697 2416600 trx_t *trx = m_prebuilt->trx;
19698
19699
1/2
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
2416600 DBUG_TRACE;
19700
19701
1/2
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
2416600 update_thd(thd);
19702
19703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2416600 times.
2416600 ut_ad(m_prebuilt->table != nullptr);
19704
19705
1/2
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
2416600 TrxInInnoDB trx_in_innodb(trx);
19706
19707
2/4
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2416600 times.
2416600 if (m_prebuilt->table->is_intrinsic()) {
19708 if (thd_sql_command(thd) == SQLCOM_ALTER_TABLE) {
19709 return HA_ERR_WRONG_COMMAND;
19710 }
19711
19712 return 0;
19713 }
19714
19715 2416600 trx = m_prebuilt->trx;
19716
19717
1/2
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
2416600 innobase_srv_conc_force_exit_innodb(trx);
19718
19719 /* Reset the AUTOINC statement level counter for multi-row INSERTs. */
19720 2416600 trx->n_autoinc_rows = 0;
19721
19722 2416600 m_prebuilt->sql_stat_start = true;
19723 2416600 m_prebuilt->hint_need_to_fetch_extra_cols = 0;
19724
1/2
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
2416600 reset_template();
19725
19726
7/8
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24988 times.
✓ Branch 3 taken 2391612 times.
✓ Branch 4 taken 24879 times.
✓ Branch 5 taken 109 times.
✓ Branch 6 taken 27 times.
✓ Branch 7 taken 2416573 times.
2441479 if (m_prebuilt->table->is_temporary() && m_mysql_has_locked &&
19727
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 24852 times.
24879 m_prebuilt->select_lock_type == LOCK_NONE) {
19728 dberr_t error;
19729
19730
3/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 25 times.
27 switch (thd_sql_command(thd)) {
19731 2 case SQLCOM_INSERT:
19732 case SQLCOM_UPDATE:
19733 case SQLCOM_DELETE:
19734 case SQLCOM_REPLACE:
19735
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 init_table_handle_for_HANDLER();
19736 2 m_prebuilt->select_lock_type = LOCK_X;
19737 2 m_stored_select_lock_type = LOCK_X;
19738
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 error = row_lock_table(m_prebuilt);
19739
19740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (error != DB_SUCCESS) {
19741 int st = convert_error_code_to_mysql(error, 0, thd);
19742 return st;
19743 }
19744 2 break;
19745 }
19746 }
19747
19748
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 2416491 times.
2416600 if (!m_mysql_has_locked) {
19749 /* This handle is for a temporary table created inside
19750 this same LOCK TABLES; since MySQL does NOT call external_lock
19751 in this case, we must use x-row locks inside InnoDB to be
19752 prepared for an update of a row */
19753
19754 109 m_prebuilt->select_lock_type = LOCK_X;
19755
19756
2/2
✓ Branch 0 taken 74550 times.
✓ Branch 1 taken 2341800 times.
2416350 } else if ((trx->isolation_level != TRX_ISO_SERIALIZABLE &&
19757
7/8
✓ Branch 0 taken 2416350 times.
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 74550 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65051 times.
✓ Branch 5 taken 9499 times.
✓ Branch 6 taken 9546 times.
✓ Branch 7 taken 2406945 times.
4898033 lock_type == TL_READ && thd_sql_command(thd) == SQLCOM_SELECT) ||
19758
5/6
✓ Branch 0 taken 2406992 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 543 times.
✓ Branch 3 taken 2406449 times.
✓ Branch 4 taken 393 times.
✓ Branch 5 taken 150 times.
2406992 (trx->skip_gap_locks() &&
19759
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 356 times.
393 (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
19760
3/4
✓ Branch 0 taken 187 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 13 times.
187 (thd_sql_command(thd) == SQLCOM_INSERT_SELECT ||
19761
3/4
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
✓ Branch 3 taken 4 times.
174 thd_sql_command(thd) == SQLCOM_REPLACE_SELECT ||
19762
3/4
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
✓ Branch 3 taken 26 times.
170 thd_sql_command(thd) == SQLCOM_UPDATE ||
19763
3/4
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 140 times.
144 thd_sql_command(thd) == SQLCOM_CREATE_TABLE))) {
19764 /* For other than temporary tables, we obtain
19765 no lock for consistent read (plain SELECT).
19766
19767 If this session is using READ COMMITTED or READ
19768 UNCOMMITTED isolation level and MySQL is doing INSERT
19769 INTO... SELECT or REPLACE INTO...SELECT or UPDATE ...
19770 = (SELECT ...) or CREATE ... SELECT... without FOR
19771 UPDATE or IN SHARE MODE in select, then we use
19772 consistent read for select.
19773
19774 See also similar code in ha_innobase::store_lock(). */
19775
19776 9546 m_prebuilt->select_lock_type = LOCK_NONE;
19777 } else {
19778 /* Not a consistent read: restore the
19779 select_lock_type value. The value of
19780 stored_select_lock_type was decided in:
19781 1) ::store_lock(),
19782 2) ::external_lock(),
19783 3) ::init_table_handle_for_HANDLER(). */
19784
19785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2406945 times.
2406945 ut_a(m_stored_select_lock_type != LOCK_NONE_UNSET);
19786
19787 2406945 m_prebuilt->select_lock_type = m_stored_select_lock_type;
19788 }
19789
19790 2416600 *trx->detailed_error = 0;
19791
19792
1/2
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
2416600 innobase_register_trx(ht, thd, trx);
19793
19794
3/4
✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84643 times.
✓ Branch 3 taken 2331957 times.
2416600 if (!trx_is_started(trx)) {
19795 84643 ++trx->will_lock;
19796 }
19797
19798 /* Only do it once per transaction. */
19799
4/4
✓ Branch 0 taken 2347622 times.
✓ Branch 1 taken 68978 times.
✓ Branch 2 taken 2347621 times.
✓ Branch 3 taken 1 times.
2416600 if (!trx->lock.start_stmt && lock_type != TL_UNLOCK) {
19800 2347621 trx->lock.start_stmt = true;
19801
1/2
✓ Branch 0 taken 2347621 times.
✗ Branch 1 not taken.
2347621 TrxInInnoDB::begin_stmt(trx);
19802 }
19803
19804 2416600 return 0;
19805 2416600 }
19806
19807 111541533 trx_t::isolation_level_t innobase_trx_map_isolation_level(
19808 enum_tx_isolation iso) {
19809 trx_t::isolation_level_t trx_isolation_level;
19810
19811
4/5
✓ Branch 0 taken 32781337 times.
✓ Branch 1 taken 67817758 times.
✓ Branch 2 taken 20212 times.
✓ Branch 3 taken 10922425 times.
✗ Branch 4 not taken.
111541533 switch (iso) {
19812 32781337 case ISO_REPEATABLE_READ:
19813 32781337 trx_isolation_level = TRX_ISO_REPEATABLE_READ;
19814 32781337 break;
19815 67817758 case ISO_READ_COMMITTED:
19816 67817758 trx_isolation_level = TRX_ISO_READ_COMMITTED;
19817 67817758 break;
19818 20212 case ISO_SERIALIZABLE:
19819 20212 trx_isolation_level = TRX_ISO_SERIALIZABLE;
19820 20212 break;
19821 10922425 case ISO_READ_UNCOMMITTED:
19822 10922425 trx_isolation_level = TRX_ISO_READ_UNCOMMITTED;
19823 10922425 break;
19824 default:
19825 ut_error;
19826 }
19827
19828 111541732 return trx_isolation_level;
19829 }
19830
19831 /** As MySQL will execute an external lock for every new table it uses when it
19832 starts to process an SQL statement (an exception is when MySQL calls
19833 start_stmt for the handle) we can use this function to store the pointer to
19834 the THD in the handle. We will also use this function to communicate
19835 to InnoDB that a new SQL statement has started and that we must store a
19836 savepoint to our transaction handle, so that we are able to roll back
19837 the SQL statement in case of an error.
19838 @return 0 */
19839
19840 224390678 int ha_innobase::external_lock(THD *thd, /*!< in: handle to the user thread */
19841 int lock_type) /*!< in: lock type */
19842 {
19843
1/2
✓ Branch 0 taken 224392416 times.
✗ Branch 1 not taken.
224390678 DBUG_TRACE;
19844
5/8
✓ Branch 0 taken 224391927 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224392202 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12050 times.
✓ Branch 5 taken 224380152 times.
✓ Branch 6 taken 12050 times.
✗ Branch 7 not taken.
224392416 DBUG_PRINT("enter", ("lock_type: %d", lock_type));
19845
19846
1/2
✓ Branch 0 taken 224392495 times.
✗ Branch 1 not taken.
224392202 update_thd(thd);
19847
19848 224392495 trx_t *trx = m_prebuilt->trx;
19849
19850
1/2
✓ Branch 0 taken 224392238 times.
✗ Branch 1 not taken.
224392495 enum_sql_command sql_command = (enum_sql_command)thd_sql_command(thd);
19851
19852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224392288 times.
224392238 ut_ad(m_prebuilt->table);
19853
19854
2/4
✓ Branch 0 taken 224392180 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 224392180 times.
224392288 if (m_prebuilt->table->is_intrinsic()) {
19855 if (sql_command == SQLCOM_ALTER_TABLE) {
19856 return HA_ERR_WRONG_COMMAND;
19857 }
19858
19859 TrxInInnoDB::begin_stmt(trx);
19860
19861 return 0;
19862 }
19863
19864 /* Statement based binlogging does not work in isolation level
19865 READ UNCOMMITTED and READ COMMITTED since the necessary
19866 locks cannot be taken. In this case, we print an
19867 informative error message and return with an error.
19868 Note: decide_logging_format would give the same error message,
19869 except it cannot give the extra details. */
19870
19871
3/4
✓ Branch 0 taken 29214887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 471280 times.
✓ Branch 3 taken 28743607 times.
29214816 if (lock_type == F_WRLCK && !(table_flags() & HA_BINLOG_STMT_CAPABLE) &&
19872
3/4
✓ Branch 0 taken 471251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8667 times.
✓ Branch 3 taken 462584 times.
471280 thd_binlog_format(thd) == BINLOG_FORMAT_STMT &&
19873
10/12
✓ Branch 0 taken 29214816 times.
✓ Branch 1 taken 195177364 times.
✓ Branch 2 taken 8667 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8663 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 8663 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 23 times.
✓ Branch 9 taken 8640 times.
✓ Branch 10 taken 23 times.
✓ Branch 11 taken 224392199 times.
253607038 thd_binlog_filter_ok(thd) && thd_sqlcom_can_generate_row_events(thd)) {
19874 23 bool skip = false;
19875
19876 /* used by test case */
19877
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
23 DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;);
19878
19879
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (!skip) {
19880
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0),
19881 " InnoDB is limited to row-logging when"
19882 " transaction isolation level is"
19883 " READ COMMITTED or READ UNCOMMITTED.");
19884
19885 23 return HA_ERR_LOGGING_IMPOSSIBLE;
19886 }
19887 }
19888
19889 /* Check for UPDATEs in read-only mode. */
19890
4/4
✓ Branch 0 taken 150361 times.
✓ Branch 1 taken 224241838 times.
✓ Branch 2 taken 150051 times.
✓ Branch 3 taken 310 times.
224392199 if (srv_read_only_mode &&
19891
4/4
✓ Branch 0 taken 149733 times.
✓ Branch 1 taken 318 times.
✓ Branch 2 taken 149732 times.
✓ Branch 3 taken 1 times.
150051 (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT ||
19892
2/4
✓ Branch 0 taken 149732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149732 times.
✗ Branch 3 not taken.
149732 sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE ||
19893
2/4
✓ Branch 0 taken 149732 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 149732 times.
149732 sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE ||
19894
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 149732 times.
✗ Branch 3 not taken.
149732 (sql_command == SQLCOM_CREATE_TABLE && lock_type == F_WRLCK) ||
19895
3/4
✓ Branch 0 taken 149732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149429 times.
✓ Branch 3 taken 303 times.
149732 sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX ||
19896
2/2
✓ Branch 0 taken 149426 times.
✓ Branch 1 taken 3 times.
149429 sql_command == SQLCOM_DELETE ||
19897
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 149422 times.
149426 sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY ||
19898 sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) {
19899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 939 times.
939 if (sql_command == SQLCOM_CREATE_TABLE) {
19900 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_INNODB_READ_ONLY);
19901 return HA_ERR_INNODB_READ_ONLY;
19902 } else {
19903
1/2
✓ Branch 0 taken 939 times.
✗ Branch 1 not taken.
939 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
19904 939 return HA_ERR_TABLE_READONLY;
19905 }
19906 }
19907
19908 224391260 m_prebuilt->sql_stat_start = true;
19909 224391260 m_prebuilt->hint_need_to_fetch_extra_cols = 0;
19910
19911
1/2
✓ Branch 0 taken 224390480 times.
✗ Branch 1 not taken.
224391260 reset_template();
19912
19913
3/4
✓ Branch 0 taken 454 times.
✓ Branch 1 taken 466 times.
✓ Branch 2 taken 224389796 times.
✗ Branch 3 not taken.
224390480 switch (m_prebuilt->table->quiesce) {
19914 454 case QUIESCE_START:
19915 /* Check for FLUSH TABLE t WITH READ LOCK; */
19916
3/6
✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 454 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 454 times.
✗ Branch 5 not taken.
454 if (!srv_read_only_mode && sql_command == SQLCOM_FLUSH &&
19917 lock_type == F_RDLCK) {
19918
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 452 times.
454 if (dict_table_is_discarded(m_prebuilt->table)) {
19919 2 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR,
19920
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ER_TABLESPACE_DISCARDED, table->s->table_name.str);
19921
19922 2 return HA_ERR_NO_SUCH_TABLE;
19923 }
19924
19925
1/2
✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
452 row_quiesce_table_start(m_prebuilt->table, trx);
19926
19927 /* Use the transaction instance to track UNLOCK
19928 TABLES. It can be done via START TRANSACTION; too
19929 implicitly. */
19930
19931 452 ++trx->flush_tables;
19932 }
19933 452 break;
19934
19935 466 case QUIESCE_COMPLETE:
19936 /* Check for UNLOCK TABLES; implicit or explicit
19937 or trx interruption. */
19938
6/6
✓ Branch 0 taken 456 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 452 times.
✓ Branch 4 taken 452 times.
✓ Branch 5 taken 14 times.
470 if (trx->flush_tables > 0 &&
19939
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 (lock_type == F_UNLCK || trx_is_interrupted(trx))) {
19940
1/2
✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
452 row_quiesce_table_complete(m_prebuilt->table, trx);
19941
19942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
452 ut_a(trx->flush_tables > 0);
19943 452 --trx->flush_tables;
19944 }
19945
19946 466 break;
19947
19948 224389796 case QUIESCE_NONE:
19949 224389796 break;
19950 }
19951
19952
2/2
✓ Branch 0 taken 29213439 times.
✓ Branch 1 taken 195177039 times.
224390478 if (lock_type == F_WRLCK) {
19953 /* If this is a SELECT, then it is in UPDATE TABLE ...
19954 or SELECT ... FOR UPDATE */
19955 29213439 m_prebuilt->select_lock_type = LOCK_X;
19956 29213439 m_stored_select_lock_type = LOCK_X;
19957 }
19958
19959
5/6
✓ Branch 0 taken 82982763 times.
✓ Branch 1 taken 141407715 times.
✓ Branch 2 taken 82982763 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 127 times.
✓ Branch 5 taken 224390369 times.
224390478 ut_ad(!(lock_type == F_RDLCK && m_prebuilt->select_lock_type == LOCK_X));
19960
19961
2/2
✓ Branch 0 taken 112196294 times.
✓ Branch 1 taken 112194075 times.
224390369 if (lock_type != F_UNLCK) {
19962 /* MySQL is setting a new table lock */
19963
19964 112196294 *trx->detailed_error = 0;
19965
19966
1/2
✓ Branch 0 taken 112196289 times.
✗ Branch 1 not taken.
112196294 innobase_register_trx(ht, thd, trx);
19967
19968 /*
19969 For reads we will use LOCK_NONE, LOCK_S or LOCK_X according to this chart:
19970 +-----------------------------------------+
19971 | is_dd_table or skip_locking |
19972 +----------------------------------+------+
19973 | false | true |
19974 +----------------------------------| |
19975 | TRANSACTION ISOLATION LEVEL | |
19976 +----------------+-----------------+ |
19977 | < SERIALIZABLE | = SERIALIZABLE | |
19978 +--------------------+----------------+-----------------+------+
19979 | non-locking SELECT | NONE [1] | S [3] | NONE |
19980 | SELECT FOR SHARE | S [2] | S | NONE |
19981 | SELECT FOR UPDATE | X | X | X |
19982 +--------------------+----------------+-----------------+------+
19983 Where LOCK_NONE means a non-locking consistent reads via read-view, and
19984 `no_read_locking` is set to `true` by Server calling
19985 ha_extra().
19986 Notes:
19987 [1,2] The server layer calls external_lock(..,F_RDLCK) which retains the old
19988 value of select_lock_type before the call. In most cases it is the value
19989 set by a previous call to store_lock(..):
19990 [1] For a non-locking SELECT the Server layer calls store_lock(..,TL_READ)
19991 which sets select_lock_type = LOCK_NONE, except for ACL tables which
19992 treat it as in [1].
19993 [2] In case of SELECT FOR SHARE the Server layer calls
19994 store_lock(..,TL_READ_WITH_SHARED_LOCKS) which sets
19995 select_lock_type = LOCK_S
19996 [3] An exception is consistent reads in the AUTOCOMMIT=1 mode:
19997 we know that they are read-only transactions, and they can be serialized
19998 also if performed as consistent reads. Thus we use LOCK_NONE for them.
19999
20000 For non-SELECT commands, there may be still possibility of setting
20001 skip_locking=1. E.g.,
20002 - UPDATE ... WHERE ... (SELECT... acl_table);
20003 - DELETE ... WHERE ... (SELECT... acl_table);
20004 The first entry 'non-locking SELECT' in above table applies in these case.
20005 */
20006
2/2
✓ Branch 0 taken 82982856 times.
✓ Branch 1 taken 29213433 times.
112196289 if (lock_type == F_RDLCK) {
20007 /**
20008 To limit range of circumstances under which transaction's isolation
20009 level can be compromised, we allow disabling readlocks only for DD
20010 and ACL tables.
20011 */
20012
8/10
✓ Branch 0 taken 2301425 times.
✓ Branch 1 taken 80681431 times.
✓ Branch 2 taken 22734 times.
✓ Branch 3 taken 2278691 times.
✓ Branch 4 taken 22734 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22734 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 82982808 times.
82982856 ut_ad(!m_prebuilt->no_read_locking || m_prebuilt->table->is_dd_table ||
20013 is_acl_table(table));
20014
20015
4/4
✓ Branch 0 taken 2553828 times.
✓ Branch 1 taken 80428980 times.
✓ Branch 2 taken 22735 times.
✓ Branch 3 taken 2531093 times.
82982808 if (m_prebuilt->table->is_dd_table || m_prebuilt->no_read_locking) {
20016 80451715 m_prebuilt->select_lock_type = LOCK_NONE;
20017 80451715 m_stored_select_lock_type = LOCK_NONE;
20018 5063585 } else if (trx->isolation_level == TRX_ISO_SERIALIZABLE &&
20019
6/6
✓ Branch 0 taken 1399 times.
✓ Branch 1 taken 2529694 times.
✓ Branch 2 taken 327 times.
✓ Branch 3 taken 1072 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 2531066 times.
2531420 m_prebuilt->select_lock_type == LOCK_NONE &&
20020
3/4
✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 300 times.
327 thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
20021 27 m_prebuilt->select_lock_type = LOCK_S;
20022 27 m_stored_select_lock_type = LOCK_S;
20023 } else {
20024 // Retain value set earlier for example via store_lock()
20025 // which is LOCK_S or LOCK_NONE
20026
4/6
✓ Branch 0 taken 1302037 times.
✓ Branch 1 taken 1229029 times.
✓ Branch 2 taken 1302037 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2531068 times.
2531066 ut_ad(m_prebuilt->select_lock_type == LOCK_S ||
20027 m_prebuilt->select_lock_type == LOCK_NONE);
20028 }
20029 }
20030
20031 /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
20032 TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
20033 an InnoDB table lock if it is released immediately at the end
20034 of LOCK TABLES, and InnoDB's table locks in that case cause
20035 VERY easily deadlocks.
20036
20037 We do not set InnoDB table locks if user has not explicitly
20038 requested a table lock. Note that thd_in_lock_tables(thd)
20039 can hold in some cases, e.g., at the start of a stored
20040 procedure call (SQLCOM_CALL). */
20041
20042
2/2
✓ Branch 0 taken 30442353 times.
✓ Branch 1 taken 81753890 times.
112196243 if (m_prebuilt->select_lock_type != LOCK_NONE) {
20043
3/4
✓ Branch 0 taken 3259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3257 times.
✓ Branch 3 taken 2 times.
3259 if (sql_command == SQLCOM_LOCK_TABLES && THDVAR(thd, table_locks) &&
20044
7/8
✓ Branch 0 taken 3259 times.
✓ Branch 1 taken 30439094 times.
✓ Branch 2 taken 3257 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 151 times.
✓ Branch 5 taken 3106 times.
✓ Branch 6 taken 151 times.
✓ Branch 7 taken 30442202 times.
30445763 thd_test_options(thd, OPTION_NOT_AUTOCOMMIT) &&
20045
2/4
✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 151 times.
✗ Branch 3 not taken.
151 thd_in_lock_tables(thd)) {
20046
1/2
✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
151 dberr_t error = row_lock_table(m_prebuilt);
20047
20048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
151 if (error != DB_SUCCESS) {
20049 return convert_error_code_to_mysql(error, 0, thd);
20050 }
20051 }
20052
20053 30442353 trx->mysql_n_tables_locked++;
20054 }
20055
20056 112196243 trx->n_mysql_tables_in_use++;
20057 112196243 m_mysql_has_locked = true;
20058
20059
7/8
✓ Branch 0 taken 112196505 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91118357 times.
✓ Branch 3 taken 21078148 times.
✓ Branch 4 taken 81459155 times.
✓ Branch 5 taken 9659202 times.
✓ Branch 6 taken 9659382 times.
✓ Branch 7 taken 102537123 times.
193655398 if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE ||
20060
2/2
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 81458781 times.
81459155 m_stored_select_lock_type != LOCK_NONE)) {
20061 9659382 ++trx->will_lock;
20062 }
20063
20064
1/2
✓ Branch 0 taken 112196779 times.
✗ Branch 1 not taken.
112196505 TrxInInnoDB::begin_stmt(trx);
20065
20066 #ifdef UNIV_DEBUG
20067
6/8
✓ Branch 0 taken 112196795 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112196564 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 78243515 times.
✓ Branch 5 taken 33953049 times.
✓ Branch 6 taken 78243525 times.
✓ Branch 7 taken 33953023 times.
112196779 if (thd != nullptr && thd_tx_is_dd_trx(thd)) {
20068 78243525 trx->is_dd_trx = true;
20069 }
20070 #endif /* UNIV_DEBUG */
20071 112196548 return 0;
20072 } else {
20073
1/2
✓ Branch 0 taken 112194222 times.
✗ Branch 1 not taken.
112194075 TrxInInnoDB::end_stmt(trx);
20074
20075
3/4
✓ Branch 0 taken 101809279 times.
✓ Branch 1 taken 10384943 times.
✓ Branch 2 taken 101809638 times.
✗ Branch 3 not taken.
112194222 DEBUG_SYNC_C("ha_innobase_end_statement");
20076 }
20077
20078 /* MySQL is releasing a table lock */
20079
20080 112194581 trx->n_mysql_tables_in_use--;
20081 112194581 m_mysql_has_locked = false;
20082
20083
1/2
✓ Branch 0 taken 112194422 times.
✗ Branch 1 not taken.
112194581 innobase_srv_conc_force_exit_innodb(trx);
20084
20085 /* If the MySQL lock count drops to zero we know that the current SQL
20086 statement has ended */
20087
20088
2/2
✓ Branch 0 taken 35504711 times.
✓ Branch 1 taken 76689711 times.
112194422 if (trx->n_mysql_tables_in_use == 0) {
20089 35504711 trx->mysql_n_tables_locked = 0;
20090 35504711 m_prebuilt->used_in_HANDLER = false;
20091
20092
3/4
✓ Branch 0 taken 35504689 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20516088 times.
✓ Branch 3 taken 14988601 times.
35504711 if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
20093
3/4
✓ Branch 0 taken 20515887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 626612 times.
✓ Branch 3 taken 19889275 times.
20516088 if (trx_is_started(trx)) {
20094
1/2
✓ Branch 0 taken 626611 times.
✗ Branch 1 not taken.
626612 innobase_commit(ht, thd, true);
20095 } else {
20096 /* Since the trx state is TRX_NOT_STARTED,
20097 trx_commit() will not be called. Reset
20098 trx->is_dd_trx here */
20099 19889275 ut_d(trx->is_dd_trx = false);
20100 }
20101
20102
4/4
✓ Branch 0 taken 373790 times.
✓ Branch 1 taken 14614811 times.
✓ Branch 2 taken 2354 times.
✓ Branch 3 taken 14986245 times.
15362389 } else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
20103
3/4
✓ Branch 0 taken 373788 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2354 times.
✓ Branch 3 taken 371434 times.
373790 MVCC::is_view_active(trx->read_view)) {
20104
1/2
✓ Branch 0 taken 2354 times.
✗ Branch 1 not taken.
2354 mutex_enter(&trx_sys->mutex);
20105
20106
1/2
✓ Branch 0 taken 2354 times.
✗ Branch 1 not taken.
2354 trx_sys->mvcc->view_close(trx->read_view, true);
20107
20108
1/2
✓ Branch 0 taken 2354 times.
✗ Branch 1 not taken.
2354 mutex_exit(&trx_sys->mutex);
20109 }
20110 }
20111
20112
5/8
✓ Branch 0 taken 112193821 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83714605 times.
✓ Branch 3 taken 28479216 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 83714605 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 112193821 times.
112194196 if (!trx_is_started(trx) && lock_type != F_UNLCK &&
20113 (m_prebuilt->select_lock_type != LOCK_NONE ||
20114 m_stored_select_lock_type != LOCK_NONE)) {
20115 ++trx->will_lock;
20116 }
20117
20118 112193821 return 0;
20119 224391333 }
20120
20121 /** Here we export InnoDB status variables to MySQL. */
20122 107957 static void innodb_export_status() {
20123
1/2
✓ Branch 0 taken 107957 times.
✗ Branch 1 not taken.
107957 if (innodb_inited) {
20124 107957 srv_export_innodb_status();
20125 }
20126 107954 }
20127
20128 /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the
20129 InnoDB Monitor to the client.
20130 @param[in] hton the innodb handlerton
20131 @param[in] thd the MySQL query thread of the caller
20132 @param[in] stat_print print function
20133 @return 0 on success */
20134 41 static int innodb_show_status(handlerton *hton, THD *thd,
20135 stat_print_fn *stat_print) {
20136 static const char truncated_msg[] = "... truncated...\n";
20137 41 const long MAX_STATUS_SIZE = 1048576;
20138 41 ulint trx_list_start = ULINT_UNDEFINED;
20139 41 ulint trx_list_end = ULINT_UNDEFINED;
20140 bool ret_val;
20141
20142
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 DBUG_TRACE;
20143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 assert(hton == innodb_hton_ptr);
20144
20145 /* We don't create the temp files or associated
20146 mutexes in read-only-mode */
20147
20148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (srv_read_only_mode) {
20149 return 0;
20150 }
20151
20152
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 trx_t *trx = check_trx_exists(thd);
20153
20154
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 innobase_srv_conc_force_exit_innodb(trx);
20155
20156
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 TrxInInnoDB trx_in_innodb(trx);
20157
20158 /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
20159 bytes of text. */
20160
20161 char *str;
20162 ssize_t flen;
20163
20164
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 mutex_enter(&srv_monitor_file_mutex);
20165
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 rewind(srv_monitor_file);
20166
20167
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 srv_printf_innodb_monitor(srv_monitor_file, false, &trx_list_start,
20168 &trx_list_end);
20169
20170
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 os_file_set_eof(srv_monitor_file);
20171
20172
2/4
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
41 if ((flen = ftell(srv_monitor_file)) < 0) {
20173 flen = 0;
20174 }
20175
20176 ssize_t usable_len;
20177
20178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (flen > MAX_STATUS_SIZE) {
20179 usable_len = MAX_STATUS_SIZE;
20180 srv_truncated_status_writes++;
20181 } else {
20182 41 usable_len = flen;
20183 }
20184
20185 /* allocate buffer for the string, and
20186 read the contents of the temporary file */
20187
20188
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 str = (char *)my_malloc(PSI_INSTRUMENT_ME, usable_len + 1, MYF(0));
20189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (!str) {
20190 mutex_exit(&srv_monitor_file_mutex);
20191 return 1;
20192 }
20193
20194
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 rewind(srv_monitor_file);
20195
20196
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 if (flen < MAX_STATUS_SIZE) {
20197 /* Display the entire output. */
20198
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 flen = fread(str, 1, flen, srv_monitor_file);
20199 } else if (trx_list_end < (ulint)flen && trx_list_start < trx_list_end &&
20200 trx_list_start + (flen - trx_list_end) <
20201 MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
20202 /* Omit the beginning of the list of active transactions. */
20203 ssize_t len = fread(str, 1, trx_list_start, srv_monitor_file);
20204
20205 memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
20206 len += sizeof truncated_msg - 1;
20207 usable_len = (MAX_STATUS_SIZE - 1) - len;
20208 fseek(srv_monitor_file, static_cast<long>(flen - usable_len), SEEK_SET);
20209 len += fread(str + len, 1, usable_len, srv_monitor_file);
20210 flen = len;
20211 } else {
20212 /* Omit the end of the output. */
20213 flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
20214 }
20215
20216
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 mutex_exit(&srv_monitor_file_mutex);
20217
20218
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 ret_val = stat_print(thd, innobase_hton_name,
20219 static_cast<uint>(strlen(innobase_hton_name)),
20220 STRING_WITH_LEN(""), str, static_cast<uint>(flen));
20221
20222
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 my_free(str);
20223
20224 41 return ret_val;
20225 41 }
20226
20227 /** Implements Log_resource lock.
20228 @param[in] hton the innodb handlerton
20229 @return false on success */
20230 26 static bool innobase_lock_hton_log(handlerton *hton) {
20231 26 bool ret_val = false;
20232
20233
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 DBUG_TRACE;
20234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 assert(hton == innodb_hton_ptr);
20235
20236
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 log_position_lock(*log_sys);
20237
20238 26 return ret_val;
20239 26 }
20240
20241 /** Implements Log_resource unlock.
20242 @param[in] hton the innodb handlerton
20243 @return false on success */
20244 26 static bool innobase_unlock_hton_log(handlerton *hton) {
20245 26 bool ret_val = false;
20246
20247
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 DBUG_TRACE;
20248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 assert(hton == innodb_hton_ptr);
20249
20250
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 log_position_unlock(*log_sys);
20251
20252 26 return ret_val;
20253 26 }
20254
20255 /** Implements Log_resource collect_info.
20256 @param[in] hton the innodb handlerton
20257 @param[in] json the JSON dom to receive the log info
20258 @return false on success */
20259 25 static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json) {
20260 25 bool ret_val = false;
20261 lsn_t lsn;
20262 lsn_t lsn_checkpoint;
20263
20264
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 DBUG_TRACE;
20265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 assert(hton == innodb_hton_ptr);
20266
20267
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 log_position_collect_lsn_info(*log_sys, &lsn, &lsn_checkpoint);
20268
20269 25 Json_object *json_engines = static_cast<Json_object *>(json);
20270
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 Json_object json_innodb;
20271 25 Json_int json_lsn(lsn);
20272 25 Json_int json_lsn_checkpoint(lsn_checkpoint);
20273
20274
2/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 ret_val = json_innodb.add_clone("LSN", &json_lsn);
20275
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (!ret_val)
20276
2/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 ret_val = json_innodb.add_clone("LSN_checkpoint", &json_lsn_checkpoint);
20277
3/6
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
25 if (!ret_val) ret_val = json_engines->add_clone("InnoDB", &json_innodb);
20278
20279 25 return ret_val;
20280 25 }
20281
20282 /** Callback for collecting mutex statistics */
20283 struct ShowStatus {
20284 /** For tracking the mutex metrics */
20285 struct Value {
20286 /** Constructor
20287 @param[in] name Name of the mutex
20288 @param[in] spins Number of spins
20289 @param[in] waits OS waits so far
20290 @param[in] calls Number of calls to enter() */
20291 Value(const char *name, ulint spins, uint64_t waits, uint64_t calls)
20292 : m_name(name), m_spins(spins), m_waits(waits), m_calls(calls) {
20293 /* No op */
20294 }
20295
20296 /** Mutex name */
20297 std::string m_name;
20298
20299 /** Spins so far */
20300 ulint m_spins;
20301
20302 /** Waits so far */
20303 uint64_t m_waits;
20304
20305 /** Number of calls so far */
20306 uint64_t m_calls;
20307 };
20308
20309 /** Order by m_waits, in descending order. */
20310 struct OrderByWaits {
20311 /** @return true if rhs < lhs */
20312 bool operator()(const Value &lhs, const Value &rhs) const UNIV_NOTHROW {
20313 return (rhs.m_waits < lhs.m_waits);
20314 }
20315 };
20316
20317 typedef std::vector<Value, ut::allocator<Value>> Values;
20318
20319 /** Collect the individual latch counts */
20320 struct GetCount {
20321 typedef latch_meta_t::CounterType::Count Count;
20322
20323 /** Constructor
20324 @param[in] name Latch name
20325 @param[in,out] values Put the values here */
20326 726 GetCount(const char *name, Values *values) UNIV_NOTHROW : m_name(name),
20327 726 m_values(values) {
20328 /* No op */
20329 726 }
20330
20331 /** Collect the latch metrics. Ignore entries where the
20332 spins and waits are zero.
20333 @param[in] count The latch metrics */
20334 19528 void operator()(const Count *count) UNIV_NOTHROW {
20335
2/4
✓ Branch 0 taken 19528 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19528 times.
19528 if (count->m_spins > 0 || count->m_waits > 0) {
20336 m_values->push_back(
20337 Value(m_name, count->m_spins, count->m_waits, count->m_calls));
20338 }
20339 19528 }
20340
20341 /** The latch name */
20342 const char *m_name;
20343
20344 /** For collecting the active mutex stats. */
20345 Values *m_values;
20346 };
20347
20348 /** Constructor */
20349 6 ShowStatus() = default;
20350
20351 /** Callback for collecting the stats
20352 @param[in] latch_meta Latch meta data
20353 @return always returns true */
20354 726 bool operator()(latch_meta_t &latch_meta) UNIV_NOTHROW {
20355
1/2
✓ Branch 0 taken 726 times.
✗ Branch 1 not taken.
1452 latch_meta.get_counter()->iterate(
20356 726 GetCount{latch_meta.get_name(), &m_values});
20357
20358 726 return (true);
20359 }
20360
20361 /** Implements the SHOW MUTEX STATUS command, for mutexes.
20362 The table structure is like so: Engine | Mutex Name | Status
20363 We store the metrics in the "Status" column as:
20364
20365 spins=N,waits=N,calls=N"
20366
20367 The user has to parse the data unfortunately
20368 @param[in,out] thd the MySQL query thread of the caller
20369 @param[in,out] stat_print function for printing statistics
20370 @return true on success. */
20371 bool to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW;
20372
20373 /** For collecting the active mutex stats. */
20374 Values m_values;
20375 };
20376
20377 /** Implements the SHOW MUTEX STATUS command, for mutexes.
20378 The table structure is like so: Engine | Mutex Name | Status
20379 We store the metrics in the "Status" column as:
20380
20381 spins=N,waits=N,calls=N"
20382
20383 The user has to parse the data unfortunately
20384 @param[in,out] thd the MySQL query thread of the caller
20385 @param[in,out] stat_print function for printing statistics
20386 @return true on success. */
20387 6 bool ShowStatus::to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW {
20388 6 uint hton_name_len = (uint)strlen(innobase_hton_name);
20389
20390
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 std::sort(m_values.begin(), m_values.end(), OrderByWaits());
20391
20392 6 Values::iterator end = m_values.end();
20393
20394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for (Values::iterator it = m_values.begin(); it != end; ++it) {
20395 int name_len;
20396 char name_buf[IO_SIZE];
20397
20398 name_len = snprintf(name_buf, sizeof(name_buf), "%s", it->m_name.c_str());
20399
20400 int status_len;
20401 char status_buf[IO_SIZE];
20402
20403 status_len = snprintf(status_buf, sizeof(status_buf),
20404 "spins=%lu,waits=%lu,calls=" TRX_ID_FMT,
20405 static_cast<ulong>(it->m_spins),
20406 static_cast<long>(it->m_waits), it->m_calls);
20407
20408 if (stat_print(thd, innobase_hton_name, hton_name_len, name_buf,
20409 static_cast<uint>(name_len), status_buf,
20410 static_cast<uint>(status_len))) {
20411 return (false);
20412 }
20413 }
20414
20415 6 return (true);
20416 }
20417
20418 /** Implements the SHOW MUTEX STATUS command, for mutexes.
20419 @param[in,out] hton the innodb handlerton
20420 @param[in,out] thd the MySQL query thread of the caller
20421 @param[in,out] stat_print function for printing statistics
20422 @return 0 on success. */
20423 6 static int innodb_show_mutex_status(handlerton *hton, THD *thd,
20424 stat_print_fn *stat_print) {
20425
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 DBUG_TRACE;
20426
20427
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 ShowStatus collector;
20428
20429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(hton == innodb_hton_ptr);
20430
20431
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mutex_monitor->iterate(collector);
20432
20433
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (!collector.to_string(thd, stat_print)) {
20434 return 1;
20435 }
20436
20437 6 return 0;
20438 6 }
20439
20440 /** Implements the SHOW MUTEX STATUS command.
20441 @param[in,out] hton the innodb handlerton
20442 @param[in,out] thd the MySQL query thread of the caller
20443 @param[in,out] stat_print function for printing statistics
20444 @return 0 on success. */
20445 6 static int innodb_show_rwlock_status(handlerton *hton, THD *thd,
20446 stat_print_fn *stat_print) {
20447
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 DBUG_TRACE;
20448
20449 6 rw_lock_t *block_rwlock = nullptr;
20450 6 ulint block_rwlock_oswait_count = 0;
20451 6 uint hton_name_len = (uint)strlen(innobase_hton_name);
20452
20453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(hton == innodb_hton_ptr);
20454
20455
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mutex_enter(&rw_lock_list_mutex);
20456
20457
6/10
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20424 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20430 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20424 times.
✓ Branch 9 taken 6 times.
20430 for (auto rw_lock : rw_lock_list) {
20458
2/2
✓ Branch 0 taken 20128 times.
✓ Branch 1 taken 296 times.
20424 if (rw_lock->count_os_wait == 0) {
20459 20337 continue;
20460 }
20461
20462 int buf1len;
20463 char buf1[IO_SIZE];
20464
20465
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 87 times.
296 if (rw_lock->is_block_lock) {
20466 209 block_rwlock = rw_lock;
20467 209 block_rwlock_oswait_count += rw_lock->count_os_wait;
20468
20469 209 continue;
20470 }
20471
20472 174 buf1len = snprintf(buf1, sizeof buf1, "rwlock: %s:%lu",
20473 innobase_basename(rw_lock->clocation.filename),
20474
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 static_cast<ulong>(rw_lock->clocation.line));
20475
20476 int buf2len;
20477 char buf2[IO_SIZE];
20478
20479 87 buf2len = snprintf(buf2, sizeof buf2, "waits=%lu",
20480 87 static_cast<ulong>(rw_lock->count_os_wait));
20481
20482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 if (stat_print(thd, innobase_hton_name, hton_name_len, buf1,
20483 87 static_cast<uint>(buf1len), buf2,
20484
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 static_cast<uint>(buf2len))) {
20485 mutex_exit(&rw_lock_list_mutex);
20486
20487 return 1;
20488 }
20489 }
20490
20491
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (block_rwlock != nullptr) {
20492 int buf1len;
20493 char buf1[IO_SIZE];
20494
20495 10 buf1len = snprintf(buf1, sizeof buf1, "sum rwlock: %s:%lu",
20496 innobase_basename(block_rwlock->clocation.filename),
20497
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 static_cast<ulong>(block_rwlock->clocation.line));
20498
20499 int buf2len;
20500 char buf2[IO_SIZE];
20501
20502 5 buf2len = snprintf(buf2, sizeof buf2, "waits=%lu",
20503 static_cast<ulong>(block_rwlock_oswait_count));
20504
20505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (stat_print(thd, innobase_hton_name, hton_name_len, buf1,
20506 5 static_cast<uint>(buf1len), buf2,
20507
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 static_cast<uint>(buf2len))) {
20508 mutex_exit(&rw_lock_list_mutex);
20509
20510 return 1;
20511 }
20512 }
20513
20514
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mutex_exit(&rw_lock_list_mutex);
20515
20516 6 return 0;
20517 6 }
20518
20519 /** Implements the SHOW MUTEX STATUS command.
20520 @param[in,out] hton the innodb handlerton
20521 @param[in,out] thd the MySQL query thread of the caller
20522 @param[in,out] stat_print function for printing statistics
20523 @return 0 on success. */
20524 6 static int innodb_show_latch_status(handlerton *hton, THD *thd,
20525 stat_print_fn *stat_print) {
20526 6 int ret = innodb_show_mutex_status(hton, thd, stat_print);
20527
20528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret != 0) {
20529 return (ret);
20530 }
20531
20532 6 return (innodb_show_rwlock_status(hton, thd, stat_print));
20533 }
20534
20535 /** Return 0 on success and non-zero on failure. Note: the bool return type
20536 seems to be abused here, should be an int.
20537 @param[in] hton the innodb handlerton
20538 @param[in] thd the MySQL query thread of the caller
20539 @param[in] stat_print print function
20540 @param[in] stat_type status to show */
20541 50 static bool innobase_show_status(handlerton *hton, THD *thd,
20542 stat_print_fn *stat_print,
20543 enum ha_stat_type stat_type) {
20544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 assert(hton == innodb_hton_ptr);
20545
20546
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
50 switch (stat_type) {
20547 41 case HA_ENGINE_STATUS:
20548 /* Non-zero return value means there was an error. */
20549 41 return (innodb_show_status(hton, thd, stat_print) != 0);
20550
20551 6 case HA_ENGINE_MUTEX:
20552 6 return (innodb_show_latch_status(hton, thd, stat_print) != 0);
20553
20554 3 case HA_ENGINE_LOGS:
20555 /* Not handled */
20556 3 break;
20557 }
20558
20559 /* Success */
20560 3 return (false);
20561 }
20562
20563 /** Handling the shared INNOBASE_SHARE structure that is needed to provide table
20564 locking. Register the table name if it doesn't exist in the hash table. */
20565 4556996 static INNOBASE_SHARE *get_share(const char *table_name) {
20566 INNOBASE_SHARE *share;
20567
20568 4556996 mysql_mutex_lock(&innobase_share_mutex);
20569
20570 4556997 const auto hash_value = ut::hash_string(table_name);
20571
20572
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2799605 times.
✓ Branch 2 taken 2496752 times.
✓ Branch 3 taken 302853 times.
✓ Branch 4 taken 2799605 times.
✓ Branch 5 taken 2060245 times.
4859850 HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value,
20573 INNOBASE_SHARE *, share, ut_ad(share->use_count > 0),
20574 !strcmp(share->table_name, table_name));
20575
20576
2/2
✓ Branch 0 taken 2060245 times.
✓ Branch 1 taken 2496752 times.
4556997 if (share == nullptr) {
20577 2060245 uint length = (uint)strlen(table_name);
20578
20579 /* TODO: invoke HASH_MIGRATE if innobase_open_tables
20580 grows too big */
20581
20582 share = reinterpret_cast<INNOBASE_SHARE *>(
20583 2060245 my_malloc(PSI_INSTRUMENT_ME, sizeof(*share) + length + 1,
20584 MYF(MY_FAE | MY_ZEROFILL)));
20585
20586 2060245 share->table_name =
20587 2060245 reinterpret_cast<char *>(memcpy(share + 1, table_name, length + 1));
20588
20589
4/4
✓ Branch 0 taken 1919077 times.
✓ Branch 1 taken 141168 times.
✓ Branch 2 taken 16575 times.
✓ Branch 3 taken 141168 times.
2076820 HASH_INSERT(INNOBASE_SHARE, table_name_hash, innobase_open_tables,
20590 hash_value, share);
20591
20592 /* Index translation table initialization */
20593 2060245 share->idx_trans_tbl.index_mapping = nullptr;
20594 2060245 share->idx_trans_tbl.index_count = 0;
20595 2060245 share->idx_trans_tbl.array_size = 0;
20596 }
20597
20598 4556997 ++share->use_count;
20599
20600 4556997 mysql_mutex_unlock(&innobase_share_mutex);
20601
20602 4556997 return (share);
20603 }
20604
20605 /** Free the shared object that was registered with get_share(). */
20606 4434067 static void free_share(
20607 INNOBASE_SHARE *share) /*!< in/own: table share to free */
20608 {
20609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4434067 times.
4434067 if (!share) {
20610 return;
20611 }
20612
20613 4434067 mysql_mutex_lock(&innobase_share_mutex);
20614
20615 #ifdef UNIV_DEBUG
20616 INNOBASE_SHARE *share2;
20617 4434068 const auto hash_value = ut::hash_string(share->table_name);
20618
20619
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4656529 times.
✓ Branch 2 taken 4434068 times.
✓ Branch 3 taken 222461 times.
✓ Branch 4 taken 4656529 times.
✗ Branch 5 not taken.
4656529 HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value,
20620 INNOBASE_SHARE *, share2, ut_ad(share->use_count > 0),
20621 !strcmp(share->table_name, share2->table_name));
20622
20623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4434068 times.
4434068 ut_a(share2 == share);
20624 #endif /* UNIV_DEBUG */
20625
20626 4434068 --share->use_count;
20627
20628
2/2
✓ Branch 0 taken 1994831 times.
✓ Branch 1 taken 2439237 times.
4434068 if (share->use_count == 0) {
20629 1994831 const auto hash_value = ut::hash_string(share->table_name);
20630
20631
5/6
✓ Branch 0 taken 1900321 times.
✓ Branch 1 taken 94510 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3690 times.
✓ Branch 4 taken 3690 times.
✓ Branch 5 taken 94510 times.
1998521 HASH_DELETE(INNOBASE_SHARE, table_name_hash, innobase_open_tables,
20632 hash_value, share);
20633
20634 /* Free any memory from index translation table */
20635 1994831 ut::free(share->idx_trans_tbl.index_mapping);
20636
20637 1994831 my_free(share);
20638
20639 /* TODO: invoke HASH_MIGRATE if innobase_open_tables
20640 shrinks too much */
20641 }
20642
20643 4434068 mysql_mutex_unlock(&innobase_share_mutex);
20644 }
20645
20646 /** Returns number of THR_LOCK locks used for one instance of InnoDB table.
20647 InnoDB no longer relies on THR_LOCK locks so 0 value is returned.
20648 Instead of THR_LOCK locks InnoDB relies on combination of metadata locks
20649 (e.g. for LOCK TABLES and DDL) and its own locking subsystem.
20650 Note that even though this method returns 0, SQL-layer still calls
20651 "::store_lock()", "::start_stmt()" and "::external_lock()" methods for InnoDB
20652 tables. */
20653
20654 112013471 uint ha_innobase::lock_count(void) const { return 0; }
20655
20656 /** Supposed to convert a MySQL table lock stored in the 'lock' field of the
20657 handle to a proper type before storing pointer to the lock into an array
20658 of pointers.
20659 In practice, since InnoDB no longer relies on THR_LOCK locks and its
20660 lock_count() method returns 0 it just informs storage engine about type
20661 of THR_LOCK which SQL-layer would have acquired for this specific statement
20662 on this specific table.
20663 MySQL also calls this if it wants to reset some table locks to a not-locked
20664 state during the processing of an SQL query. An example is that during a
20665 SELECT the read lock is released early on the 'const' tables where we only
20666 fetch one row. MySQL does not call this when it releases all locks at the
20667 end of an SQL statement.
20668 @return pointer to the current element in the 'to' array. */
20669
20670 112013862 THR_LOCK_DATA **ha_innobase::store_lock(
20671 THD *thd, /*!< in: user thread handle */
20672 THR_LOCK_DATA **to, /*!< in: pointer to the current
20673 element in an array of pointers
20674 to lock structs;
20675 only used as return value */
20676 thr_lock_type lock_type) /*!< in: lock type to store in
20677 'lock'; this may also be
20678 TL_IGNORE */
20679 {
20680 /* Note that trx in this function is NOT necessarily m_prebuilt->trx
20681 because we call update_thd() later, in ::external_lock()! Failure to
20682 understand this caused a serious memory corruption bug in 5.1.11. */
20683
20684
1/2
✓ Branch 0 taken 112014783 times.
✗ Branch 1 not taken.
112013862 trx_t *trx = check_trx_exists(thd);
20685
20686
1/2
✓ Branch 0 taken 112014231 times.
✗ Branch 1 not taken.
112014783 TrxInInnoDB trx_in_innodb(trx);
20687
20688 /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE!
20689 Be careful to ignore TL_IGNORE if we are going to do something with
20690 only 'real' locks! */
20691
20692 /* If no MySQL table is in use, we need to set the isolation level
20693 of the transaction. */
20694
20695
4/4
✓ Branch 0 taken 111918847 times.
✓ Branch 1 taken 95384 times.
✓ Branch 2 taken 111542011 times.
✓ Branch 3 taken 376836 times.
112014231 if (lock_type != TL_IGNORE && trx->n_mysql_tables_in_use == 0) {
20696 111541634 trx->isolation_level =
20697
2/4
✓ Branch 0 taken 111541665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111541634 times.
✗ Branch 3 not taken.
111542011 innobase_trx_map_isolation_level(thd_get_trx_isolation(thd));
20698
20699
4/4
✓ Branch 0 taken 78740215 times.
✓ Branch 1 taken 32801419 times.
✓ Branch 2 taken 198 times.
✓ Branch 3 taken 111541392 times.
190281805 if (trx->isolation_level <= TRX_ISO_READ_COMMITTED &&
20700
3/4
✓ Branch 0 taken 78740171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
✓ Branch 3 taken 78739973 times.
78740215 MVCC::is_view_active(trx->read_view)) {
20701 /* At low transaction isolation levels we let
20702 each consistent read set its own snapshot */
20703
20704
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 mutex_enter(&trx_sys->mutex);
20705
20706
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 trx_sys->mvcc->view_close(trx->read_view, true);
20707
20708
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
198 mutex_exit(&trx_sys->mutex);
20709 }
20710 }
20711
20712
2/4
✓ Branch 0 taken 112013756 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 112013756 times.
112013810 assert(EQ_CURRENT_THD(thd));
20713
1/2
✓ Branch 0 taken 112013858 times.
✗ Branch 1 not taken.
112013756 const bool in_lock_tables = thd_in_lock_tables(thd);
20714
1/2
✓ Branch 0 taken 112014064 times.
✗ Branch 1 not taken.
112013858 const uint sql_command = thd_sql_command(thd);
20715
20716
8/10
✓ Branch 0 taken 75589 times.
✓ Branch 1 taken 111938475 times.
✓ Branch 2 taken 75589 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 75589 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 75279 times.
✓ Branch 7 taken 310 times.
✓ Branch 8 taken 940 times.
✓ Branch 9 taken 112013124 times.
112089343 if (srv_read_only_mode && !m_prebuilt->table->is_intrinsic() &&
20717
4/4
✓ Branch 0 taken 74960 times.
✓ Branch 1 taken 319 times.
✓ Branch 2 taken 74959 times.
✓ Branch 3 taken 1 times.
75279 (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT ||
20718
2/4
✓ Branch 0 taken 74959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74959 times.
✗ Branch 3 not taken.
74959 sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE ||
20719
2/4
✓ Branch 0 taken 74959 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74959 times.
74959 sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE ||
20720 (sql_command == SQLCOM_CREATE_TABLE &&
20721
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 74959 times.
✗ Branch 3 not taken.
74959 (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE)) ||
20722
3/4
✓ Branch 0 taken 74959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74656 times.
✓ Branch 3 taken 303 times.
74959 sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX ||
20723
2/2
✓ Branch 0 taken 74653 times.
✓ Branch 1 taken 3 times.
74656 sql_command == SQLCOM_DELETE ||
20724
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 74649 times.
74653 sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY ||
20725 sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) {
20726
1/2
✓ Branch 0 taken 940 times.
✗ Branch 1 not taken.
940 ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
20727
20728
4/4
✓ Branch 0 taken 129665 times.
✓ Branch 1 taken 111883459 times.
✓ Branch 2 taken 464 times.
✓ Branch 3 taken 129201 times.
112013124 } else if (sql_command == SQLCOM_FLUSH && lock_type == TL_READ_NO_INSERT) {
20729 /* Check for FLUSH TABLES ... WITH READ LOCK */
20730
20731 /* Note: This call can fail, but there is no way to return
20732 the error to the caller. We simply ignore it for now here
20733 and push the error code to the caller where the error is
20734 detected in the function. */
20735
20736
1/2
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
464 dberr_t err = row_quiesce_set_state(m_prebuilt->table, QUIESCE_START, trx);
20737
20738
4/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 456 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 464 times.
464 ut_a(err == DB_SUCCESS || err == DB_UNSUPPORTED);
20739
20740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (trx->isolation_level == TRX_ISO_SERIALIZABLE) {
20741 m_prebuilt->select_lock_type = LOCK_S;
20742 m_stored_select_lock_type = LOCK_S;
20743 } else {
20744 464 m_prebuilt->select_lock_type = LOCK_NONE;
20745 464 m_stored_select_lock_type = LOCK_NONE;
20746 }
20747
20748 /* Check for DROP TABLE */
20749
2/2
✓ Branch 0 taken 112011950 times.
✓ Branch 1 taken 710 times.
112013124 } else if (sql_command == SQLCOM_DROP_TABLE) {
20750 /* MySQL calls this function in DROP TABLE though this table
20751 handle may belong to another thd that is running a query. Let
20752 us in that case skip any changes to the m_prebuilt struct. */
20753
20754 /* Check for LOCK TABLE t1,...,tn WITH SHARED LOCKS */
20755
6/6
✓ Branch 0 taken 82619359 times.
✓ Branch 1 taken 29392591 times.
✓ Branch 2 taken 82617954 times.
✓ Branch 3 taken 1405 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 112010525 times.
112011950 } else if ((lock_type == TL_READ && in_lock_tables) ||
20756
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112010371 times.
✓ Branch 3 taken 174 times.
112010545 (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables) ||
20757
2/2
✓ Branch 0 taken 111918728 times.
✓ Branch 1 taken 91643 times.
112010371 lock_type == TL_READ_WITH_SHARED_LOCKS ||
20758
2/2
✓ Branch 0 taken 111823515 times.
✓ Branch 1 taken 95213 times.
111918728 lock_type == TL_READ_NO_INSERT ||
20759
2/2
✓ Branch 0 taken 31267057 times.
✓ Branch 1 taken 80556458 times.
111823515 (lock_type != TL_IGNORE && sql_command != SQLCOM_SELECT)) {
20760 /* The OR cases above are in this order:
20761 1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
20762 are processing a stored procedure or function, or
20763 2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
20764 3) this is a SELECT ... IN SHARE MODE/FOR SHARE, or
20765 4) we are doing a complex SQL statement like
20766 INSERT INTO ... SELECT ... and the logical logging (MySQL
20767 binlog) requires the use of a locking read, or
20768 MySQL is doing LOCK TABLES ... READ.
20769 5) we let InnoDB do locking reads for all SQL statements that
20770 are not simple SELECTs; note that select_lock_type in this
20771 case may get strengthened in ::external_lock() to LOCK_X.
20772 Note that we MUST use a locking read in all data modifying
20773 SQL statements, because otherwise the execution would not be
20774 serializable, and also the results from the update could be
20775 unexpected if an obsolete consistent read view would be
20776 used. */
20777
20778 /* Use consistent read for checksum table */
20779
20780
4/4
✓ Branch 0 taken 30693666 times.
✓ Branch 1 taken 666613 times.
✓ Branch 2 taken 667071 times.
✓ Branch 3 taken 30693177 times.
62053914 if (sql_command == SQLCOM_CHECKSUM ||
20781
5/6
✓ Branch 0 taken 30693635 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478067 times.
✓ Branch 3 taken 30215568 times.
✓ Branch 4 taken 471476 times.
✓ Branch 5 taken 6591 times.
30693666 (trx->skip_gap_locks() &&
20782
4/4
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 471103 times.
✓ Branch 2 taken 6639 times.
✓ Branch 3 taken 325 times.
478067 (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
20783
2/2
✓ Branch 0 taken 6635 times.
✓ Branch 1 taken 4 times.
6639 (sql_command == SQLCOM_INSERT_SELECT ||
20784
2/2
✓ Branch 0 taken 6574 times.
✓ Branch 1 taken 61 times.
6635 sql_command == SQLCOM_REPLACE_SELECT ||
20785
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 6522 times.
6574 sql_command == SQLCOM_UPDATE ||
20786 sql_command == SQLCOM_CREATE_TABLE))) {
20787 /* If this session is using READ COMMITTED or READ
20788 UNCOMMITTED isolation level and MySQL is doing INSERT
20789 INTO... SELECT or REPLACE INTO...SELECT or UPDATE ...
20790 = (SELECT ...) or CREATE ... SELECT... without FOR
20791 UPDATE or IN SHARE MODE in select, then we use
20792 consistent read for select.
20793
20794 See also similar code in ha_innobase::start_stmt(). */
20795
20796 667071 m_prebuilt->select_lock_type = LOCK_NONE;
20797 667071 m_stored_select_lock_type = LOCK_NONE;
20798 } else {
20799 30693177 m_prebuilt->select_lock_type = LOCK_S;
20800 30693177 m_stored_select_lock_type = LOCK_S;
20801 }
20802
20803
2/2
✓ Branch 0 taken 80557087 times.
✓ Branch 1 taken 94584 times.
80651671 } else if (lock_type != TL_IGNORE) {
20804 /* We set possible LOCK_X value in external_lock, not yet
20805 here even if this would be SELECT ... FOR UPDATE */
20806
20807 80557087 m_prebuilt->select_lock_type = LOCK_NONE;
20808 80557087 m_stored_select_lock_type = LOCK_NONE;
20809 }
20810
20811 /* Set select mode for SKIP LOCKED / NOWAIT */
20812
2/2
✓ Branch 0 taken 111918527 times.
✓ Branch 1 taken 95506 times.
112014033 if (lock_type != TL_IGNORE) {
20813
3/3
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 111918555 times.
111918527 switch (table->pos_in_table_list->lock_descriptor().action) {
20814 100 case THR_SKIP:
20815 100 m_prebuilt->select_mode = SELECT_SKIP_LOCKED;
20816 100 break;
20817 96 case THR_NOWAIT:
20818 96 m_prebuilt->select_mode = SELECT_NOWAIT;
20819 96 break;
20820 111918555 default:
20821 111918555 m_prebuilt->select_mode = SELECT_ORDINARY;
20822 111918555 break;
20823 }
20824 }
20825
20826 /* Ignore SKIP LOCKED / NO_WAIT for high priority transaction */
20827
3/4
✓ Branch 0 taken 112013573 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213088 times.
✓ Branch 3 taken 111800485 times.
112014257 if (trx_is_high_priority(trx)) {
20828 213088 m_prebuilt->select_mode = SELECT_ORDINARY;
20829 }
20830
20831
7/8
✓ Branch 0 taken 112014114 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91125924 times.
✓ Branch 3 taken 20888190 times.
✓ Branch 4 taken 81218172 times.
✓ Branch 5 taken 9907752 times.
✓ Branch 6 taken 9907801 times.
✓ Branch 7 taken 102106313 times.
193231745 if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE ||
20832
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 81218132 times.
81218172 m_stored_select_lock_type != LOCK_NONE)) {
20833 9907801 ++trx->will_lock;
20834 }
20835
20836 #ifdef UNIV_DEBUG
20837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112014114 times.
112014114 if (trx->is_dd_trx) {
20838 ut_ad(trx->will_lock == 0 && m_prebuilt->select_lock_type == LOCK_NONE);
20839 }
20840 #endif /* UNIV_DEBUG */
20841
20842 112014639 return (to);
20843 112014114 }
20844
20845 /** Read the next autoinc value. Acquire the relevant locks before reading
20846 the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
20847 on return and all relevant locks acquired.
20848 @return DB_SUCCESS or error code */
20849
20850 8033551 dberr_t ha_innobase::innobase_get_autoinc(
20851 ulonglong *value) /*!< out: autoinc value */
20852 {
20853 8033551 *value = 0;
20854
20855 8033551 m_prebuilt->autoinc_error = innobase_lock_autoinc();
20856
20857
1/2
✓ Branch 0 taken 8033608 times.
✗ Branch 1 not taken.
8033594 if (m_prebuilt->autoinc_error == DB_SUCCESS) {
20858 /* Determine the first value of the interval */
20859 8033608 *value = dict_table_autoinc_read(m_prebuilt->table);
20860
20861 /* It should have been initialized during open. */
20862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8033613 times.
8033613 if (*value == 0) {
20863 m_prebuilt->autoinc_error = DB_UNSUPPORTED;
20864 dict_table_autoinc_unlock(m_prebuilt->table);
20865 }
20866 }
20867
20868 8033620 return (m_prebuilt->autoinc_error);
20869 }
20870
20871 20936658 void ha_innobase::release_auto_increment() {
20872 20936658 trx_t *trx = m_prebuilt->trx;
20873
1/2
✓ Branch 0 taken 20936670 times.
✗ Branch 1 not taken.
20936658 TrxInInnoDB trx_in_innodb(trx);
20874
20875 /* Clear the trx's autoinc_rows as the operation requiring auto increment
20876 values has been completed.
20877
20878 We usually end up in this scenario when we do not know the correct estimation
20879 of rows in the table in the case of bulk inserts. */
20880
2/2
✓ Branch 0 taken 7424 times.
✓ Branch 1 taken 20929246 times.
20936670 if (trx->n_autoinc_rows > 0) {
20881 7424 trx->n_autoinc_rows = 0;
20882 }
20883 20936670 }
20884
20885 /** Returns the value of the auto-inc counter in *first_value and ~0 on failure.
20886 */
20887
20888 8033472 void ha_innobase::get_auto_increment(
20889 ulonglong offset, /*!< in: table autoinc offset */
20890 ulonglong increment, /*!< in: table autoinc
20891 increment */
20892 ulonglong nb_desired_values, /*!< in: number of values
20893 reqd */
20894 ulonglong *first_value, /*!< out: the autoinc value */
20895 ulonglong *nb_reserved_values) /*!< out: count of reserved
20896 values */
20897 {
20898 trx_t *trx;
20899 dberr_t error;
20900 8033472 ulonglong autoinc = 0;
20901
20902 /* Prepare m_prebuilt->trx in the table handle */
20903
2/4
✓ Branch 0 taken 8033648 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8033666 times.
✗ Branch 3 not taken.
8033472 update_thd(ha_thd());
20904
20905
1/2
✓ Branch 0 taken 8033622 times.
✗ Branch 1 not taken.
8033666 error = innobase_get_autoinc(&autoinc);
20906
20907
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8033621 times.
8033622 if (error != DB_SUCCESS) {
20908 1 *first_value = (~(ulonglong)0);
20909 1 return;
20910 }
20911
20912 /* This is a hack, since nb_desired_values seems to be accurate only
20913 for the first call to get_auto_increment() for multi-row INSERT and
20914 meaningless for other statements e.g, LOAD etc. Subsequent calls to
20915 this method for the same statement results in different values which
20916 don't make sense. Therefore we store the value the first time we are
20917 called and count down from that as rows are written (see write_row()).
20918 */
20919
20920 8033621 trx = m_prebuilt->trx;
20921
20922
1/2
✓ Branch 0 taken 8033642 times.
✗ Branch 1 not taken.
8033621 TrxInInnoDB trx_in_innodb(trx);
20923
20924 /* Note: We can't rely on *first_value since some MySQL engines,
20925 in particular the partition engine, don't initialize it to 0 when
20926 invoking this method. So we are not sure if it's guaranteed to
20927 be 0 or not. */
20928
20929 /* We need the upper limit of the col type to check for
20930 whether we update the table autoinc counter or not. */
20931
1/2
✓ Branch 0 taken 8033658 times.
✗ Branch 1 not taken.
8033642 ulonglong col_max_value = table->next_number_field->get_max_int_value();
20932
20933 /** The following logic is needed to avoid duplicate key error
20934 for autoincrement column.
20935
20936 (1) InnoDB gives the current autoincrement value with respect
20937 to increment and offset value.
20938
20939 (2) Basically it does compute_next_insert_id() logic inside InnoDB
20940 to avoid the current auto increment value changed by handler layer.
20941
20942 (3) It is restricted only for insert operations. */
20943
20944
4/4
✓ Branch 0 taken 5808 times.
✓ Branch 1 taken 8027850 times.
✓ Branch 2 taken 5806 times.
✓ Branch 3 taken 2 times.
8033658 if (increment > 1 && m_prebuilt->table->skip_alter_undo == false &&
20945
2/2
✓ Branch 0 taken 5798 times.
✓ Branch 1 taken 8 times.
5806 autoinc < col_max_value) {
20946 5798 ulonglong diff = ULLONG_MAX - autoinc;
20947 /* Check for overflow */
20948
2/2
✓ Branch 0 taken 5796 times.
✓ Branch 1 taken 2 times.
5798 if (increment <= diff) {
20949 5796 ulonglong prev_auto_inc = autoinc;
20950 5796 autoinc = ((autoinc - 1) + increment - offset) / increment;
20951 5796 autoinc = autoinc * increment + offset;
20952
20953 /* If autoinc exceeds the col_max_value then reset
20954 to old autoinc value. Because in case of non-strict
20955 sql mode, boundary value is not considered as error. */
20956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5796 times.
5796 if (autoinc >= col_max_value) {
20957 autoinc = prev_auto_inc;
20958 }
20959
20960
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 5699 times.
5796 ut_ad(autoinc > 0);
20961 }
20962 }
20963
20964 /* Called for the first time ? */
20965
2/2
✓ Branch 0 taken 8033487 times.
✓ Branch 1 taken 74 times.
8033561 if (trx->n_autoinc_rows == 0) {
20966 8033487 trx->n_autoinc_rows = (ulint)nb_desired_values;
20967
20968 /* It's possible for nb_desired_values to be 0:
20969 e.g., INSERT INTO T1(C) SELECT C FROM T2; */
20970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8033487 times.
8033487 if (nb_desired_values == 0) {
20971 trx->n_autoinc_rows = 1;
20972 }
20973
20974 8033487 *first_value = std::max(*first_value, autoinc);
20975 /* Not in the middle of a mult-row INSERT. */
20976
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 56 times.
74 } else if (m_prebuilt->autoinc_last_value == 0) {
20977 18 *first_value = std::max(*first_value, autoinc);
20978 /* Check for -ve values. */
20979
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
56 } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
20980 /* Set to next logical value. */
20981 ut_a(autoinc > trx->n_autoinc_rows);
20982 *first_value = (autoinc - trx->n_autoinc_rows) - 1;
20983 }
20984
20985 8033553 *nb_reserved_values = trx->n_autoinc_rows;
20986
20987 /* With old style AUTOINC locking we only update the table's
20988 AUTOINC counter after attempting to insert the row. */
20989
2/2
✓ Branch 0 taken 10959 times.
✓ Branch 1 taken 8022594 times.
8033553 if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING ||
20990
2/2
✓ Branch 0 taken 8041 times.
✓ Branch 1 taken 2918 times.
10959 m_prebuilt->no_autoinc_locking) {
20991 ulonglong current;
20992 ulonglong next_value;
20993
20994
2/2
✓ Branch 0 taken 8030593 times.
✓ Branch 1 taken 42 times.
8030635 current = *first_value > col_max_value ? autoinc : *first_value;
20995
20996 /* Compute the last value in the interval */
20997
1/2
✓ Branch 0 taken 8030737 times.
✗ Branch 1 not taken.
8030635 next_value = innobase_next_autoinc(current, *nb_reserved_values, increment,
20998 offset, col_max_value);
20999
21000 8030737 m_prebuilt->autoinc_last_value = next_value;
21001
21002
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8030736 times.
8030737 if (m_prebuilt->autoinc_last_value < *first_value) {
21003 1 *first_value = (~(ulonglong)0);
21004 } else {
21005 /* Update the table autoinc variable */
21006 8030736 dict_table_autoinc_update_if_greater(m_prebuilt->table,
21007
1/2
✓ Branch 0 taken 8030714 times.
✗ Branch 1 not taken.
8030736 m_prebuilt->autoinc_last_value);
21008 }
21009 8030715 } else {
21010 /* This will force write_row() into attempting an update
21011 of the table's AUTOINC counter. */
21012 2918 m_prebuilt->autoinc_last_value = 0;
21013 }
21014
21015 /* The increment to be used to increase the AUTOINC value, we use
21016 this in write_row() and update_row() to increase the autoinc counter
21017 for columns that are filled by the user. We need the offset and
21018 the increment. */
21019 8033633 m_prebuilt->autoinc_offset = offset;
21020 8033633 m_prebuilt->autoinc_increment = increment;
21021
21022
1/2
✓ Branch 0 taken 8033623 times.
✗ Branch 1 not taken.
8033633 dict_table_autoinc_unlock(m_prebuilt->table);
21023 8033623 }
21024
21025 /** See comment in handler.cc */
21026
21027 557 bool ha_innobase::get_error_message(int error, String *buf) {
21028 557 trx_t *trx = check_trx_exists(ha_thd());
21029
21030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 557 times.
557 if (error == HA_ERR_ENCRYPTION_KEY_MISSING) {
21031 const char *msg =
21032 "Table encrypted but decryption key was not found. "
21033 "Is correct keyring loaded?";
21034 buf->copy(msg, (uint)strlen(msg), system_charset_info);
21035 } else {
21036 557 buf->copy(trx->detailed_error, (uint)strlen(trx->detailed_error),
21037 system_charset_info);
21038 }
21039
21040 557 return false;
21041 }
21042
21043 /** Retrieves the names of the table and the key for which there was a
21044 duplicate entry in the case of HA_ERR_FOREIGN_DUPLICATE_KEY.
21045
21046 If any of the names is not available, then this method will return
21047 false and will not change any of child_table_name or child_key_name.
21048
21049 @param[out] child_table_name Table name
21050 @param[in] child_table_name_len Table name buffer size
21051 @param[out] child_key_name Key name
21052 @param[in] child_key_name_len Key name buffer size
21053
21054 @retval true table and key names were available and were written into the
21055 corresponding out parameters.
21056 @retval false table and key names were not available, the out parameters
21057 were not touched. */
21058 3 bool ha_innobase::get_foreign_dup_key(char *child_table_name,
21059 uint child_table_name_len,
21060 char *child_key_name,
21061 uint child_key_name_len) {
21062 const dict_index_t *err_index;
21063
21064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 ut_a(m_prebuilt->trx != nullptr);
21065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
21066
21067 3 err_index = trx_get_error_index(m_prebuilt->trx);
21068
21069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (err_index == nullptr) {
21070 return (false);
21071 }
21072 /* else */
21073
21074 /* copy table name (and convert from filename-safe encoding to
21075 system_charset_info) */
21076 3 char *p = strchr(err_index->table->name.m_name, '/');
21077
21078 /* strip ".../" prefix if any */
21079
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (p != nullptr) {
21080 3 p++;
21081 } else {
21082 p = err_index->table->name.m_name;
21083 }
21084
21085 size_t len;
21086
21087 3 len = filename_to_tablename(p, child_table_name, child_table_name_len);
21088
21089 3 child_table_name[len] = '\0';
21090
21091 /* copy index name */
21092 3 snprintf(child_key_name, child_key_name_len, "%s", err_index->name());
21093
21094 3 return (true);
21095 }
21096
21097 /** Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
21098 If there is no explicitly declared non-null unique key or a primary key, then
21099 InnoDB internally uses the row id as the primary key.
21100 @return < 0 if ref1 < ref2, 0 if equal, else > 0 */
21101
21102 2374704 int ha_innobase::cmp_ref(
21103 const uchar *ref1, /*!< in: an (internal) primary key value in the
21104 MySQL key value format */
21105 const uchar *ref2) /*!< in: an (internal) primary key value in the
21106 MySQL key value format */
21107 const {
21108 enum_field_types mysql_type;
21109 Field *field;
21110 KEY_PART_INFO *key_part;
21111 KEY_PART_INFO *key_part_end;
21112 uint len1;
21113 uint len2;
21114 int result;
21115
21116
2/2
✓ Branch 0 taken 1507624 times.
✓ Branch 1 taken 867080 times.
2374704 if (m_prebuilt->clust_index_was_generated) {
21117 /* The 'ref' is an InnoDB row id */
21118
21119 1507624 return (memcmp(ref1, ref2, DATA_ROW_ID_LEN));
21120 }
21121
21122 /* Do a type-aware comparison of primary key fields. PK fields
21123 are always NOT NULL, so no checks for NULL are performed. */
21124
21125 867080 key_part = table->key_info[table->s->primary_key].key_part;
21126
21127 867080 key_part_end =
21128 867080 key_part + table->key_info[table->s->primary_key].user_defined_key_parts;
21129
21130
2/2
✓ Branch 0 taken 867697 times.
✓ Branch 1 taken 97446 times.
965143 for (; key_part != key_part_end; ++key_part) {
21131 867697 field = key_part->field;
21132 867697 mysql_type = field->type();
21133
21134
2/4
✓ Branch 0 taken 867697 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 867697 times.
✗ Branch 3 not taken.
867697 if (mysql_type == MYSQL_TYPE_TINY_BLOB ||
21135
3/4
✓ Branch 0 taken 867634 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 867634 times.
867697 mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB ||
21136 mysql_type == MYSQL_TYPE_LONG_BLOB) {
21137 /* In the MySQL key value format, a column prefix of
21138 a BLOB is preceded by a 2-byte length field */
21139
21140 63 len1 = innobase_read_from_2_little_endian(ref1);
21141 63 len2 = innobase_read_from_2_little_endian(ref2);
21142
21143 63 result =
21144 63 down_cast<Field_blob *>(field)->cmp(ref1 + 2, len1, ref2 + 2, len2);
21145 } else {
21146 867634 result = field->key_cmp(ref1, ref2);
21147 }
21148
21149
2/2
✓ Branch 0 taken 769634 times.
✓ Branch 1 taken 98063 times.
867697 if (result) {
21150 769634 return (result);
21151 }
21152
21153 98063 ref1 += key_part->store_length;
21154 98063 ref2 += key_part->store_length;
21155 }
21156
21157 97446 return (0);
21158 }
21159
21160 /** This function is used to find the storage length in bytes of the first n
21161 characters for prefix indexes using a multibyte character set. The function
21162 finds charset information and returns length of prefix_len characters in the
21163 index field in bytes.
21164 @return number of bytes occupied by the first n characters */
21165 206316 ulint innobase_get_at_most_n_mbchars(
21166 ulint charset_id, /*!< in: character set id */
21167 ulint prefix_len, /*!< in: prefix length in bytes of the index
21168 (this has to be divided by mbmaxlen to get the
21169 number of CHARACTERS n in the prefix) */
21170 ulint data_len, /*!< in: length of the string in bytes */
21171 const char *str) /*!< in: character string */
21172 {
21173 ulint char_length; /*!< character length in bytes */
21174 ulint n_chars; /*!< number of characters in prefix */
21175 CHARSET_INFO *charset; /*!< charset used in the field */
21176
21177 206316 charset = get_charset((uint)charset_id, MYF(MY_WME));
21178
21179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206322 times.
206321 ut_ad(charset);
21180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 206322 times.
206322 ut_ad(charset->mbmaxlen);
21181
21182 /* Calculate how many characters at most the prefix index contains */
21183
21184 206322 n_chars = prefix_len / charset->mbmaxlen;
21185
21186 /* If the charset is multi-byte, then we must find the length of the
21187 first at most n chars in the string. If the string contains less
21188 characters than n, then we return the length to the end of the last
21189 character. */
21190
21191
1/2
✓ Branch 0 taken 206322 times.
✗ Branch 1 not taken.
206322 if (charset->mbmaxlen > 1) {
21192 /* my_charpos() returns the byte length of the first n_chars
21193 characters, or a value bigger than the length of str, if
21194 there were not enough full characters in str.
21195
21196 Why does the code below work:
21197 Suppose that we are looking for n UTF-8 characters.
21198
21199 1) If the string is long enough, then the prefix contains at
21200 least n complete UTF-8 characters + maybe some extra
21201 characters + an incomplete UTF-8 character. No problem in
21202 this case. The function returns the pointer to the
21203 end of the nth character.
21204
21205 2) If the string is not long enough, then the string contains
21206 the complete value of a column, that is, only complete UTF-8
21207 characters, and we can store in the column prefix index the
21208 whole string. */
21209
21210 206322 char_length = my_charpos(charset, str, str + data_len, (int)n_chars);
21211
2/2
✓ Branch 0 taken 155133 times.
✓ Branch 1 taken 51196 times.
206329 if (char_length > data_len) {
21212 155133 char_length = data_len;
21213 }
21214 } else if (data_len < prefix_len) {
21215 char_length = data_len;
21216
21217 } else {
21218 char_length = prefix_len;
21219 }
21220
21221 206329 return (char_length);
21222 }
21223
21224 /** This function is used to prepare an X/Open XA distributed transaction.
21225 @return 0 or error number */
21226 7283262 static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */
21227 THD *thd, /*!< in: handle to the MySQL thread of
21228 the user whose XA transaction should
21229 be prepared */
21230 bool prepare_trx) /*!< in: true - prepare
21231 transaction false - the current
21232 SQL statement ended */
21233 {
21234
1/2
✓ Branch 0 taken 7283329 times.
✗ Branch 1 not taken.
7283262 trx_t *trx = check_trx_exists(thd);
21235
21236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7283329 times.
7283329 assert(hton == innodb_hton_ptr);
21237
21238
1/2
✓ Branch 0 taken 7283287 times.
✗ Branch 1 not taken.
7283329 thd_get_xid(thd, (MYSQL_XID *)trx->xid);
21239
21240
1/2
✓ Branch 0 taken 7283312 times.
✗ Branch 1 not taken.
7283287 innobase_srv_conc_force_exit_innodb(trx);
21241
21242
1/2
✓ Branch 0 taken 7283285 times.
✗ Branch 1 not taken.
7283312 TrxInInnoDB trx_in_innodb(trx);
21243
21244
5/6
✓ Branch 0 taken 7283326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7283035 times.
✓ Branch 3 taken 291 times.
✓ Branch 4 taken 293 times.
✓ Branch 5 taken 7283024 times.
14566311 if (trx_in_innodb.is_aborted() ||
21245
3/4
✓ Branch 0 taken 7283026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7283024 times.
7283035 DBUG_EVALUATE_IF("simulate_xa_failure_prepare_in_engine", 1, 0)) {
21246
1/2
✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
293 innobase_rollback(hton, thd, prepare_trx);
21247
21248
1/2
✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
293 return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd));
21249 }
21250
21251
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7282979 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7282979 times.
7283024 if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
21252 log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE);
21253 }
21254
21255
4/4
✓ Branch 0 taken 6785781 times.
✓ Branch 1 taken 497208 times.
✓ Branch 2 taken 1977525 times.
✓ Branch 3 taken 5305472 times.
14068778 if (prepare_trx ||
21256
3/4
✓ Branch 0 taken 6785789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1480309 times.
✓ Branch 3 taken 5305480 times.
6785781 (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
21257 /* We were instructed to prepare the whole transaction, or
21258 this is an SQL statement end and autocommit is on */
21259
21260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1977536 times.
1977525 ut_ad(trx_is_registered_for_2pc(trx));
21261
21262
1/2
✓ Branch 0 taken 1977544 times.
✗ Branch 1 not taken.
1977536 dberr_t err = trx_prepare_for_mysql(trx);
21263
21264
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1977540 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1977552 times.
1977544 ut_ad(err == DB_SUCCESS || err == DB_FORCED_ABORT);
21265
21266
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1977548 times.
1977552 if (err == DB_FORCED_ABORT) {
21267
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 innobase_rollback(hton, thd, prepare_trx);
21268
21269
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd));
21270 }
21271
21272
4/6
✓ Branch 0 taken 1977548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1977545 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
1977548 DBUG_EXECUTE_IF("crash_innodb_after_prepare", DBUG_SUICIDE(););
21273
21274 } else {
21275 /* We just mark the SQL statement ended and do not do a
21276 transaction prepare */
21277
21278 /* If we had reserved the auto-inc lock for some
21279 table in this SQL statement we release it now */
21280
21281
1/2
✓ Branch 0 taken 5305482 times.
✗ Branch 1 not taken.
5305472 lock_unlock_table_autoinc(trx);
21282
21283 /* Store the current undo_no of the transaction so that we
21284 know where to roll back if we have to roll back the next
21285 SQL statement */
21286
21287
1/2
✓ Branch 0 taken 5305484 times.
✗ Branch 1 not taken.
5305482 trx_mark_sql_stat_end(trx);
21288 }
21289
21290
5/6
✓ Branch 0 taken 7283029 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7282403 times.
✓ Branch 3 taken 626 times.
✓ Branch 4 taken 6785821 times.
✓ Branch 5 taken 496582 times.
14068849 if (thd_sql_command(thd) != SQLCOM_XA_PREPARE &&
21291 6785820 (prepare_trx ||
21292
3/4
✓ Branch 0 taken 6785820 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1480338 times.
✓ Branch 3 taken 5305482 times.
6785821 !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
21293 /* For mysqlbackup to work the order of transactions in binlog
21294 and InnoDB must be the same. Consider the situation
21295
21296 thread1> prepare; write to binlog; ...
21297 <context switch>
21298 thread2> prepare; write to binlog; commit
21299 thread1> ... commit
21300
21301 The server guarantees that writes to the binary log
21302 and commits are in the same order, so we do not have
21303 to handle this case. */
21304 }
21305
21306 7283028 return (0);
21307 7283325 }
21308
21309 /** This function is used to recover X/Open XA distributed transactions.
21310 @return number of prepared transactions stored in xid_list */
21311 11837 static int innobase_xa_recover(
21312 handlerton *hton, /*!< in: InnoDB handlerton */
21313 XA_recover_txn *txn_list, /*!< in/out: prepared transactions */
21314 uint len, /*!< in: number of slots in xid_list */
21315 MEM_ROOT *mem_root) /*!< in: memory for table names */
21316 {
21317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11837 times.
11837 assert(hton == innodb_hton_ptr);
21318
21319
2/4
✓ Branch 0 taken 11837 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11837 times.
11837 if (len == 0 || txn_list == nullptr) {
21320 return (0);
21321 }
21322
21323 11837 return (trx_recover_for_mysql(txn_list, len, mem_root));
21324 }
21325
21326 11837 static int innobase_xa_recover_prepared_in_tc(handlerton *hton,
21327 Xa_state_list &xa_list) {
21328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11837 times.
11837 assert(hton == innodb_hton_ptr);
21329
21330 11837 return (trx_recover_tc_for_mysql(xa_list));
21331 }
21332
21333 /** This function is used to commit one X/Open XA distributed transaction
21334 which is in the prepared state
21335 @return 0 or error number */
21336 619 static xa_status_code innobase_commit_by_xid(
21337 handlerton *hton, XID *xid) /*!< in: X/Open XA transaction identification */
21338 {
21339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
619 assert(hton == innodb_hton_ptr);
21340
21341 619 trx_t *trx = trx_get_trx_by_xid(xid);
21342
21343
2/2
✓ Branch 0 taken 603 times.
✓ Branch 1 taken 16 times.
619 if (trx != nullptr) {
21344
1/2
✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
603 TrxInInnoDB trx_in_innodb(trx);
21345
21346
1/2
✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
603 innobase_commit_low(trx);
21347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 603 times.
603 ut_ad(trx->mysql_thd == nullptr);
21348 /* use cases are: disconnected xa, slave xa, recovery */
21349 603 trx_deregister_from_2pc(trx);
21350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 603 times.
603 ut_ad(!trx->will_lock); /* trx cache requirement */
21351
1/2
✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
603 trx_free_for_background(trx);
21352
21353 603 return (XA_OK);
21354 603 } else {
21355 16 return (XAER_NOTA);
21356 }
21357 }
21358
21359 /** This function is used to rollback one X/Open XA distributed transaction
21360 which is in the prepared state
21361 @return 0 or error number */
21362 327 static xa_status_code innobase_rollback_by_xid(
21363 handlerton *hton, /*!< in: InnoDB handlerton */
21364 XID *xid) /*!< in: X/Open XA transaction
21365 identification */
21366 {
21367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327 times.
327 assert(hton == innodb_hton_ptr);
21368
21369 327 trx_t *trx = trx_get_trx_by_xid(xid);
21370
21371
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 15 times.
327 if (trx != nullptr) {
21372
1/2
✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
312 TrxInInnoDB trx_in_innodb(trx);
21373
21374
1/2
✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
312 int ret = innobase_rollback_trx(trx);
21375
21376 312 trx_deregister_from_2pc(trx);
21377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 ut_ad(!trx->will_lock);
21378
1/2
✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
312 trx_free_for_background(trx);
21379
21380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
312 return (ret != 0 ? XAER_RMERR : XA_OK);
21381 312 } else {
21382 15 return (XAER_NOTA);
21383 }
21384 }
21385
21386 587 static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd) {
21387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
587 assert(hton == innodb_hton_ptr);
21388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
587 assert(thd != nullptr);
21389
21390 587 trx_t *trx = check_trx_exists(thd);
21391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
587 assert(trx != nullptr);
21392
21393 587 thd_get_xid(thd, (MYSQL_XID *)trx->xid);
21394
21395 587 innobase_srv_conc_force_exit_innodb(trx);
21396
21397
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 587 times.
587 ut_ad(trx_is_registered_for_2pc(trx) || thd == nullptr);
21398
21399 587 dberr_t err = trx_set_prepared_in_tc_for_mysql(trx);
21400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
587 ut_ad(err != DB_FORCED_ABORT);
21401
21402 587 return convert_error_code_to_mysql(err, 0, thd);
21403 }
21404
21405 62 static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton,
21406 XID *xid) {
21407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(hton == innodb_hton_ptr);
21408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(xid != nullptr);
21409
21410 62 trx_t *trx = trx_get_trx_by_xid(xid);
21411
21412
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (trx != nullptr) {
21413 /* Side effect of retrieving the transaction is XID being set to null */
21414 62 *trx->xid = *xid;
21415
21416
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
62 if (trx_is_prepared_in_tc(trx)) {
21417 56 return XA_OK;
21418 }
21419
21420 6 innobase_srv_conc_force_exit_innodb(trx);
21421
21422 6 dberr_t err = trx_set_prepared_in_tc_for_mysql(trx);
21423
21424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 ut_ad(err != DB_FORCED_ABORT);
21425
21426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 return (err != DB_SUCCESS ? XAER_RMERR : XA_OK);
21427 } else {
21428 return (XAER_NOTA);
21429 }
21430 }
21431
21432 /** */
21433
21434 249 bool ha_innobase::check_if_incompatible_data(HA_CREATE_INFO *info,
21435 uint table_changes) {
21436 249 innobase_copy_frm_flags_from_create_info(m_prebuilt->table, info);
21437
21438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (table_changes != IS_EQUAL_YES) {
21439 return (COMPATIBLE_DATA_NO);
21440 }
21441
21442 /* Check that auto_increment value was not changed */
21443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if ((info->used_fields & HA_CREATE_USED_AUTO) &&
21444 info->auto_increment_value != 0) {
21445 return (COMPATIBLE_DATA_NO);
21446 }
21447
21448 /* Check that row format didn't change */
21449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) &&
21450 info->row_type != table->s->real_row_type) {
21451 return (COMPATIBLE_DATA_NO);
21452 }
21453
21454 /* Specifying KEY_BLOCK_SIZE requests a rebuild of the table. */
21455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
249 if (info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) {
21456 return (COMPATIBLE_DATA_NO);
21457 }
21458
21459 249 return (COMPATIBLE_DATA_YES);
21460 }
21461
21462 /** This function reads zip dict-related info from SYS_ZIP_DICT
21463 and SYS_ZIP_DICT_COLS for all columns marked with
21464 COLUMN_FORMAT_TYPE_COMPRESSED flag and updates
21465 zip_dict_name / zip_dict_data for those which have associated
21466 compression dictionaries.
21467
21468 @param thd Thread handle, used to determine whether it is
21469 necessary to lock dict_sys mutex
21470 @param part_name Full table name (including partition part).
21471 Must be non-NULL only if called from
21472 ha_partition.
21473 */
21474 33 void ha_innobase::upgrade_update_field_with_zip_dict_info(
21475 THD *thd, const char *part_name) {
21476
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 DBUG_ENTER("upgrade_update_field_with_zip_dict_info");
21477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 ut_ad(srv_is_upgrade_mode);
21478
21479 char norm_name[FN_REFLEN];
21480
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
51 normalize_table_name(
21481 18 norm_name, part_name ? part_name : table_share->normalized_path.str);
21482
21483
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 const innodb_session_t *const innodb_session = thd_to_innodb_session(thd);
21484 33 bool dict_locked = innodb_session->is_dict_mutex_locked();
21485
21486
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 dict_table_t *const ib_table = dict_table_open_on_name(
21487 norm_name, dict_locked, false, DICT_ERR_IGNORE_NONE);
21488
21489 /* if dict_table_open_on_name() returns NULL, then it means that
21490 TABLE_SHARE is populated for a table being created and we can
21491 skip filling zip dict info here */
21492
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
33 if (ib_table == nullptr) DBUG_VOID_RETURN;
21493
21494 33 const table_id_t ib_table_id = ib_table->id - DICT_MAX_DD_TABLES;
21495
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 dict_table_close(ib_table, dict_locked, false);
21496
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 33 times.
102 for (uint i = 0; i < table_share->fields; ++i) {
21497 69 Field *const field = table_share->field[i];
21498
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 30 times.
69 if (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) {
21499 39 bool reference_found = false;
21500 39 ulint dict_id = 0;
21501
3/5
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
39 switch (dict_get_dictionary_id_by_key(ib_table_id, i, &dict_id)) {
21502 24 case DB_SUCCESS:
21503 24 reference_found = true;
21504 24 break;
21505 15 case DB_RECORD_NOT_FOUND:
21506 15 reference_found = false;
21507 15 break;
21508 default:
21509 ut_error;
21510 }
21511
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 15 times.
39 if (reference_found) {
21512 24 char *local_name = nullptr;
21513 24 ulint local_name_len = 0;
21514 24 char *local_data = nullptr;
21515 24 ulint local_data_len = 0;
21516
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (dict_get_dictionary_info_by_id(dict_id, &local_name,
21517 &local_name_len, &local_data,
21518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 &local_data_len) != DB_SUCCESS)
21519 ut_error;
21520 else {
21521 24 field->zip_dict_name.str = local_name;
21522 24 field->zip_dict_name.length = local_name_len;
21523 24 field->zip_dict_data.str = local_data;
21524 24 field->zip_dict_data.length = local_data_len;
21525 }
21526 } else {
21527 15 field->zip_dict_name.str = nullptr;
21528 15 field->zip_dict_name.length = 0;
21529 15 field->zip_dict_data.str = nullptr;
21530 15 field->zip_dict_data.length = 0;
21531 }
21532 }
21533 }
21534
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 DBUG_VOID_RETURN;
21535 }
21536
21537 /** Update the system variable innodb_io_capacity_max using the "saved"
21538 value. This function is registered as a callback with MySQL. */
21539 10 static void innodb_io_capacity_max_update(
21540 THD *thd, /*!< in: thread handle */
21541 SYS_VAR *, /*!< in: pointer to
21542 system variable */
21543 void *, /*!< out: where the
21544 formal string goes */
21545 const void *save) /*!< in: immediate result
21546 from check function */
21547 {
21548 10 ulong in_val = *static_cast<const ulong *>(save);
21549
21550
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (in_val < srv_io_capacity) {
21551 2 in_val = srv_io_capacity;
21552 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21553 "innodb_io_capacity_max cannot be"
21554 " set lower than innodb_io_capacity.");
21555 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21556 "Setting innodb_io_capacity_max to %lu",
21557 srv_io_capacity);
21558 }
21559
21560 10 srv_max_io_capacity = in_val;
21561 10 }
21562
21563 /** Update the system variable innodb_io_capacity using the "saved"
21564 value. This function is registered as a callback with MySQL. */
21565 18 static void innodb_io_capacity_update(
21566 THD *thd, /*!< in: thread handle */
21567 SYS_VAR *, /*!< in: pointer to system variable */
21568 void *, /*!< out: where the formal string goes */
21569 const void *save) /*!< in: immediate result from check function */
21570 {
21571 18 ulong in_val = *static_cast<const ulong *>(save);
21572
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 17 times.
18 if (in_val > srv_max_io_capacity) {
21573 1 in_val = srv_max_io_capacity;
21574 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21575 "innodb_io_capacity cannot be set"
21576 " higher than innodb_io_capacity_max.");
21577 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21578 "Setting innodb_io_capacity to %lu",
21579 srv_max_io_capacity);
21580 }
21581
21582 18 srv_io_capacity = in_val;
21583 18 }
21584
21585 /** Update the system variable innodb_max_dirty_pages_pct using the "saved"
21586 value. This function is registered as a callback with MySQL. */
21587 36 static void innodb_max_dirty_pages_pct_update(
21588 THD *thd, /*!< in: thread handle */
21589 SYS_VAR *, /*!< in: pointer to
21590 system variable */
21591 void *, /*!< out: where the
21592 formal string goes */
21593 const void *save) /*!< in: immediate result
21594 from check function */
21595 {
21596 36 double in_val = *static_cast<const double *>(save);
21597
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
36 if (in_val < srv_max_dirty_pages_pct_lwm) {
21598 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21599 "innodb_max_dirty_pages_pct cannot be"
21600 " set lower than"
21601 " innodb_max_dirty_pages_pct_lwm.");
21602 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21603 "Lowering"
21604 " innodb_max_dirty_page_pct_lwm to %lf",
21605 in_val);
21606
21607 2 srv_max_dirty_pages_pct_lwm = in_val;
21608 }
21609
21610 36 srv_max_buf_pool_modified_pct = in_val;
21611 36 }
21612
21613 /** Update the system variable innodb_max_dirty_pages_pct_lwm using the
21614 "saved" value. This function is registered as a callback with MySQL. */
21615 20 static void innodb_max_dirty_pages_pct_lwm_update(
21616 THD *thd, /*!< in: thread handle */
21617 SYS_VAR *, /*!< in: pointer to
21618 system variable */
21619 void *, /*!< out: where the
21620 formal string goes */
21621 const void *save) /*!< in: immediate result
21622 from check function */
21623 {
21624 20 double in_val = *static_cast<const double *>(save);
21625
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (in_val > srv_max_buf_pool_modified_pct) {
21626 2 in_val = srv_max_buf_pool_modified_pct;
21627 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21628 "innodb_max_dirty_pages_pct_lwm"
21629 " cannot be set higher than"
21630 " innodb_max_dirty_pages_pct.");
21631 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21632 "Setting innodb_max_dirty_page_pct_lwm"
21633 " to %lf",
21634 in_val);
21635 }
21636
21637 20 srv_max_dirty_pages_pct_lwm = in_val;
21638 20 }
21639
21640 39 static int innodb_stopword_table_validate(THD *thd, SYS_VAR *, void *save,
21641 struct st_mysql_value *value) {
21642 const char *stopword_table_name;
21643 char buff[STRING_BUFFER_USUAL_SIZE];
21644 39 int len = sizeof(buff);
21645 39 int ret = 1;
21646
21647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 ut_a(save != nullptr);
21648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 ut_a(value != nullptr);
21649
21650
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 stopword_table_name = value->val_str(value, buff, &len);
21651
21652
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
39 if (stopword_table_name != nullptr) {
21653
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
25 if (stopword_table_name == buff) {
21654 /* Allocate from thd's memroot */
21655
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 stopword_table_name = thd_strmake(thd, stopword_table_name, len);
21656 }
21657 }
21658
21659 /* Validate the stopword table's (if supplied) existence and
21660 of the right format */
21661
7/8
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 34 times.
✓ Branch 7 taken 5 times.
39 if (!stopword_table_name || fts_valid_stopword_table(stopword_table_name)) {
21662 34 *static_cast<const char **>(save) = stopword_table_name;
21663 34 ret = 0;
21664 }
21665
21666 39 return (ret);
21667 }
21668
21669 /**
21670 Utility method that checks if user provided valid value.
21671 If yes, then store that in the save variable.
21672 @return 0 on success, 1 on failure.
21673 */
21674 1165 static int check_func_bool(THD *, SYS_VAR *, void *save,
21675 st_mysql_value *value) {
21676 int result;
21677
2/2
✓ Branch 0 taken 969 times.
✓ Branch 1 taken 196 times.
1165 if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) {
21678 char buff[STRING_BUFFER_USUAL_SIZE];
21679 969 int length = sizeof(buff);
21680
21681
1/2
✓ Branch 0 taken 969 times.
✗ Branch 1 not taken.
969 const char *str = value->val_str(value, buff, &length);
21682
21683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 969 times.
973 if (str == nullptr) return 1;
21684
21685
1/2
✓ Branch 0 taken 969 times.
✗ Branch 1 not taken.
969 result = find_type(&bool_typelib, str, length, true) - 1;
21686
21687
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 965 times.
969 if (result < 0) return 1;
21688 } else {
21689 long long tmp;
21690
2/4
✓ Branch 0 taken 196 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 196 times.
204 if (value->val_int(value, &tmp) < 0) return 1;
21691
4/4
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 188 times.
196 if (tmp > 1 || tmp < 0) return 1;
21692 188 result = static_cast<int>(tmp);
21693 }
21694 1153 *(bool *)save = result ? true : false;
21695 1153 return 0;
21696 }
21697
21698 /**
21699 Utility method that checks if user has correct session administrative
21700 dynamic privileges.
21701 @return 0 on success, 1 on failure.
21702 */
21703 990 static int check_session_admin(THD *thd) {
21704 990 Security_context *sctx = thd->security_context();
21705 990 if (!sctx->has_global_grant(STRING_WITH_LEN("SESSION_VARIABLES_ADMIN"))
21706
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 987 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 989 times.
993 .first &&
21707 3 !sctx->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN"))
21708
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 .first) {
21709 1 return 1;
21710 }
21711 989 return 0;
21712 }
21713
21714 /**
21715 Check if SESSION_VARIABLES_ADMIN granted. Throw SQL error if not.
21716 We also accept SYSTEM_VARIABLES_ADMIN since it doesn't make a lot of
21717 sense to be allowed to set the global variable and not the session ones.
21718
21719 @param thd the session context
21720 @param var the system variable to set value for
21721 @param save set the updated value
21722 @param value A struct that reads us the values from mysqld
21723
21724 @retval 1 failure
21725 @retval 0 success
21726 */
21727 990 static int innodb_check_session_admin(THD *thd, SYS_VAR *var, void *save,
21728 struct st_mysql_value *value) {
21729
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 989 times.
990 if (check_session_admin(thd)) {
21730 1 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
21731 "SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
21732 1 return 1;
21733 }
21734 989 return check_func_bool(thd, var, save, value);
21735 }
21736
21737 5 static void innodb_srv_buffer_pool_in_core_file_update(THD *, SYS_VAR *, void *,
21738 const void *save) {
21739 5 srv_buffer_pool_in_core_file = *(bool *)save;
21740 5 buf_pool_update_madvise();
21741 5 }
21742
21743 /** Validate the requested buffer pool size. Also, reserve the necessary
21744 memory needed for buffer pool resize.
21745 @param[in] thd thread handle
21746 @param[in] buffer_pool_size buffer pool size value to be validated
21747 @param[out] aligned_buffer_pool_size aligned version of buffer_pool_size
21748 if validation succeeds, else original value passed in
21749 @return true on success, false on failure.
21750 */
21751 30 static bool innodb_buffer_pool_size_validate(THD *thd,
21752 longlong buffer_pool_size,
21753 ulint &aligned_buffer_pool_size) {
21754 30 os_rmb;
21755
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29 times.
30 if (srv_buf_pool_old_size != srv_buf_pool_size) {
21756 1 push_warning(thd, ER_BUFPOOL_RESIZE_INPROGRESS);
21757 1 return false;
21758 }
21759
21760
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
29 if (srv_buf_pool_instances > 1 &&
21761 buffer_pool_size < BUF_POOL_SIZE_THRESHOLD) {
21762 #ifdef UNIV_DEBUG
21763 /* Ignore 1G constraint to enable mulitple instances
21764 for debug and test. */
21765
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (srv_buf_pool_debug) {
21766 2 goto debug_set;
21767 }
21768 #endif /* UNIV_DEBUG */
21769
21770 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21771 "Cannot update innodb_buffer_pool_size"
21772 " to less than 1GB if"
21773 " innodb_buffer_pool_instances > 1.");
21774 return false;
21775 }
21776
21777 #ifdef UNIV_DEBUG
21778 27 debug_set:
21779 #endif /* UNIV_DEBUG */
21780
21781 if constexpr (sizeof(ulint) == 4) {
21782 if (buffer_pool_size > UINT_MAX32) {
21783 push_warning_printf(
21784 thd, Sql_condition::SL_WARNING, ER_WRONG_VALUE_FOR_VAR,
21785 ER_THD(thd, ER_WRONG_VALUE_FOR_VAR), "innodb_buffer_pool_size",
21786 std::to_string(buffer_pool_size).c_str());
21787 return false;
21788 }
21789 }
21790
21791
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
29 if (!innodb_empty_free_list_algorithm_allowed(
21792 static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm),
21793 buffer_pool_size)) {
21794 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21795 "Cannot update innodb_buffer_pool_size to less than "
21796 "20MB per instance with "
21797 "innodb_empty_free_list_algorithm = backoff.");
21798 1 return false;
21799 }
21800
21801 28 aligned_buffer_pool_size =
21802 28 buf_pool_size_align(static_cast<ulint>(buffer_pool_size));
21803
21804
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
28 if (srv_buf_pool_size == static_cast<ulint>(buffer_pool_size)) {
21805 /* nothing to do */
21806
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
25 } else if (srv_buf_pool_size == aligned_buffer_pool_size) {
21807 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
21808 "InnoDB: Cannot resize buffer pool to lesser than"
21809 " chunk size of %llu bytes.",
21810 srv_buf_pool_chunk_unit);
21811 } else {
21812 23 srv_buf_pool_size = aligned_buffer_pool_size;
21813 23 os_wmb;
21814
21815
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
23 if (buffer_pool_size != static_cast<longlong>(aligned_buffer_pool_size)) {
21816
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 push_warning_printf(
21817 thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE,
21818 ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "innodb_buffer_pool_size",
21819 14 std::to_string(buffer_pool_size).c_str());
21820 }
21821 }
21822
21823 28 return true;
21824 }
21825
21826 /** Set the variable tbsp_extend_and_initialize. This function is registered
21827 as a callback to MySQL.
21828 On Linux, the variable tbsp_extend_and_initialize will be set to the value
21829 passed by the user. A warning will be printed that the user is not
21830 allowed to change the value if the server is running on Windows
21831 or other posix implementations.
21832 @param[in] thd thread handle
21833 @param[out] var_ptr value to be set after the validation
21834 @param[in] save value set by the user */
21835 19 static void innodb_extend_and_initialize_update(THD *thd, SYS_VAR *,
21836 void *var_ptr,
21837 const void *save) {
21838 19 bool extend_and_initialize [[maybe_unused]] =
21839 *static_cast<const bool *>(save);
21840 #if !defined(NO_FALLOCATE) && defined(UNIV_LINUX)
21841 19 *static_cast<bool *>(var_ptr) = extend_and_initialize;
21842 #else /* !NO_FALLOCATE && UNIV_LINUX */
21843 push_warning_printf(thd, Sql_condition::SL_WARNING,
21844 ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED,
21845 ER_THD(thd, ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED),
21846 "innodb_extend_and_initialize");
21847 *static_cast<bool *>(var_ptr) = true;
21848 #endif /* !NO_FALLOCATE && UNIV_LINUX */
21849 19 }
21850
21851 /** Update the system variable innodb_buffer_pool_size using the "saved"
21852 value. This function is registered as a callback with MySQL.
21853 @param[in] thd thread handle
21854 @param[out] var_ptr where the formal string goes
21855 @param[in] save immediate result from check function */
21856 30 static void innodb_buffer_pool_size_update(THD *thd, SYS_VAR *, void *var_ptr,
21857 const void *save) {
21858 30 longlong requested_buffer_pool_size = *static_cast<const longlong *>(save);
21859 30 ulint aligned_buffer_pool_size = 0u;
21860
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
30 if (innodb_buffer_pool_size_validate(thd, requested_buffer_pool_size,
21861 aligned_buffer_pool_size)) {
21862 28 snprintf(export_vars.innodb_buffer_pool_resize_status,
21863 sizeof(export_vars.innodb_buffer_pool_resize_status),
21864 "Requested to resize buffer pool.");
21865
21866
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 os_event_set(srv_buf_resize_event);
21867
21868
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
56 ib::info(ER_IB_MSG_573)
21869
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 << export_vars.innodb_buffer_pool_resize_status
21870
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 << " (new size: " << aligned_buffer_pool_size << " bytes)";
21871
21872 28 *static_cast<longlong *>(var_ptr) = aligned_buffer_pool_size;
21873 }
21874 30 }
21875
21876 /** Update the system variable innobase_deadlock_detect using the "saved" value.
21877 Makes sure to "wake up" the dedicated deadlock detector thread if needed.
21878 This function is registered as a callback with MySQL.
21879 @param[in] save immediate result from check function */
21880 14 static void innobase_deadlock_detect_update(THD *, SYS_VAR *, void *,
21881 const void *save) {
21882 14 innobase_deadlock_detect = *(bool *)save;
21883 /* In case deadlock detection was disabled for a long time it could happen
21884 that all clients have deadlocked with each other and thus they stopped
21885 changing the wait-for graph, which in turn causes deadlock detection to not
21886 observe any action and thus it will not search for deadlocks. So if we now
21887 change from OFF to ON we need to "kick-start" the process. It never hurts to
21888 do so, so we do it even if we check from ON to OFF */
21889 14 lock_wait_request_check_for_cycles();
21890 14 }
21891
21892 /** Check whether valid argument given to "innodb_fts_internal_tbl_name"
21893 This function is registered as a callback with MySQL.
21894 @param[in] thd thread handle
21895 @param[out] save immediate result for update function
21896 @param[in] value incoming string
21897 @return 0 for valid stopword table */
21898 32 static int innodb_internal_table_validate(THD *thd, SYS_VAR *, void *save,
21899 struct st_mysql_value *value) {
21900 const char *table_name;
21901 char buff[STRING_BUFFER_USUAL_SIZE];
21902 32 int len = sizeof(buff);
21903 32 int ret = 1;
21904 dict_table_t *user_table;
21905 32 MDL_ticket *mdl = nullptr;
21906
21907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 ut_a(save != nullptr);
21908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 ut_a(value != nullptr);
21909
21910
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 table_name = value->val_str(value, buff, &len);
21911
21912
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 24 times.
32 if (!table_name) {
21913 8 *static_cast<const char **>(save) = nullptr;
21914 8 return (0);
21915
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 } else if (table_name == buff) {
21916 /* Allocate memory from thd's mem_root */
21917
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 table_name = thd_strmake(thd, table_name, len);
21918 }
21919
21920 /* If name is longer than NAME_LEN, no need to try to open it */
21921
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (len >= NAME_LEN) {
21922 2 return (1);
21923 }
21924
21925 user_table =
21926
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 dd_table_open_on_name(thd, &mdl, table_name, false, DICT_ERR_IGNORE_NONE);
21927
21928
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
22 if (user_table) {
21929
3/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 1 times.
21 if (dict_table_has_fts_index(user_table)) {
21930 20 *static_cast<const char **>(save) = table_name;
21931 20 ret = 0;
21932 }
21933
21934
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 dd_table_close(user_table, thd, &mdl, false);
21935
21936
6/10
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
21 DBUG_EXECUTE_IF("innodb_evict_autoinc_table", dict_sys_mutex_enter();
21937 dict_table_remove_from_cache_debug(user_table, true);
21938 dict_sys_mutex_exit(););
21939 }
21940
21941 22 return (ret);
21942 }
21943
21944 /** Update the system variable innodb_adaptive_hash_index using the "saved"
21945 value. This function is registered as a callback with MySQL. */
21946 17 static void innodb_adaptive_hash_index_update(
21947 THD *, /*!< in: thread handle */
21948 SYS_VAR *, /*!< in: pointer to
21949 system variable */
21950 void *, /*!< out: where the
21951 formal string goes */
21952 const void *save) /*!< in: immediate result
21953 from check function */
21954 {
21955
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
17 if (*(bool *)save) {
21956 11 btr_search_enable(true);
21957 } else {
21958 6 btr_search_disable(true);
21959 }
21960 17 }
21961
21962 /** Update the system variable innodb_cmp_per_index using the "saved"
21963 value. This function is registered as a callback with MySQL. */
21964 75 static void innodb_cmp_per_index_update(
21965 THD *, /*!< in: thread handle */
21966 SYS_VAR *, /*!< in: pointer to
21967 system variable */
21968 void *, /*!< out: where the
21969 formal string goes */
21970 const void *save) /*!< in: immediate result
21971 from check function */
21972 {
21973 /* Reset the stats whenever we enable the table
21974 INFORMATION_SCHEMA.innodb_cmp_per_index. */
21975
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 4 times.
75 if (!srv_cmp_per_index_enabled && *(bool *)save) {
21976 36 page_zip_reset_stat_per_index();
21977 }
21978
21979 75 srv_cmp_per_index_enabled = *(bool *)save;
21980 75 }
21981
21982 /** Update the system variable innodb_old_blocks_pct using the "saved"
21983 value. This function is registered as a callback with MySQL. */
21984 11 static void innodb_old_blocks_pct_update(
21985 THD *, /*!< in: thread handle */
21986 SYS_VAR *, /*!< in: pointer to
21987 system variable */
21988 void *, /*!< out: where the
21989 formal string goes */
21990 const void *save) /*!< in: immediate result
21991 from check function */
21992 {
21993 11 innobase_old_blocks_pct = static_cast<uint>(
21994 11 buf_LRU_old_ratio_update(*static_cast<const uint *>(save), true));
21995 11 }
21996
21997 /** Update the system variable innodb_old_blocks_pct using the "saved"
21998 value. This function is registered as a callback with MySQL. */
21999 12 static void innodb_change_buffer_max_size_update(
22000 THD *, /*!< in: thread handle */
22001 SYS_VAR *, /*!< in: pointer to
22002 system variable */
22003 void *, /*!< out: where the
22004 formal string goes */
22005 const void *save) /*!< in: immediate result
22006 from check function */
22007 {
22008 12 srv_change_buffer_max_size = (*static_cast<const uint *>(save));
22009 12 ibuf_max_size_update(srv_change_buffer_max_size);
22010 12 }
22011
22012 #ifdef UNIV_DEBUG
22013 static ulong srv_fil_make_page_dirty_debug = 0;
22014 static ulong srv_saved_page_number_debug = 0;
22015
22016 /** Save an InnoDB page number. */
22017 61 static void innodb_save_page_no(THD *, /*!< in: thread handle */
22018 SYS_VAR *, /*!< in: pointer to
22019 system variable */
22020 void *, /*!< out: where the
22021 formal string goes */
22022 const void *save) /*!< in: immediate result
22023 from check function */
22024 {
22025 61 srv_saved_page_number_debug = *static_cast<const ulong *>(save);
22026
22027
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
122 ib::info(ER_IB_MSG_1257) << "Saving InnoDB page number: "
22028
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 << srv_saved_page_number_debug;
22029 61 }
22030
22031 /** Make the first page of given user tablespace dirty. */
22032 57 static void innodb_make_page_dirty(THD *, /*!< in: thread handle */
22033 SYS_VAR *, /*!< in: pointer to
22034 system variable */
22035 void *, /*!< out: where the
22036 formal string goes */
22037 const void *save) /*!< in: immediate result
22038 from check function */
22039 {
22040
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 mtr_t mtr;
22041 57 ulong space_id = *static_cast<const ulong *>(save);
22042 57 page_no_t page_no = srv_saved_page_number_debug;
22043
22044
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 fil_space_t *space = fil_space_acquire_silent(space_id);
22045
22046
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 52 times.
57 if (space == nullptr) {
22047 5 return;
22048 }
22049
22050
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
52 if (page_no > space->size) {
22051
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fil_space_release(space);
22052 2 return;
22053 }
22054
22055 50 auto page_id = page_id_t{space->id, page_no};
22056
22057
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mtr.start();
22058
22059
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
50 buf_block_t *block = buf_page_get(page_id, page_size_t(space->flags),
22060 RW_X_LATCH, UT_LOCATION_HERE, &mtr);
22061
22062
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (block != nullptr) {
22063 50 byte *page = block->frame;
22064
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 page_type_t page_type = fil_page_get_type(page);
22065
22066 /* Don't dirty a page that is not yet used. */
22067
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1 times.
50 if (page_type != FIL_PAGE_TYPE_ALLOCATED) {
22068
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 ib::info(ER_IB_MSG_574)
22069
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 << "Dirtying page: " << page_id
22070
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 << ", page_type=" << fil_get_page_type_str(page_type);
22071
22072 49 dblwr::Force_crash = page_id;
22073
22074
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 mlog_write_ulint(page + FIL_PAGE_TYPE, page_type, MLOG_2BYTES, &mtr);
22075 }
22076 }
22077
22078
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mtr.commit();
22079
22080
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 fil_space_release(space);
22081
22082
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (block != nullptr) {
22083
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
50 buf_flush_sync_all_buf_pools();
22084 }
22085
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 }
22086 #endif // UNIV_DEBUG
22087
22088 /** Update the monitor counter according to the "set_option", turn
22089 on/off or reset specified monitor counter. */
22090 9634 static void innodb_monitor_set_option(
22091 const monitor_info_t *monitor_info, /*!< in: monitor info for the monitor
22092 to set */
22093 mon_option_t set_option) /*!< in: Turn on/off reset the
22094 counter */
22095 {
22096 9634 monitor_id_t monitor_id = monitor_info->monitor_id;
22097
22098 /* If module type is MONITOR_GROUP_MODULE, it cannot be
22099 turned on/off individually. It should never use this
22100 function to set options */
22101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9634 times.
9634 ut_a(!(monitor_info->monitor_type & MONITOR_GROUP_MODULE));
22102
22103
4/5
✓ Branch 0 taken 5981 times.
✓ Branch 1 taken 3317 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 294 times.
✗ Branch 4 not taken.
9634 switch (set_option) {
22104 5981 case MONITOR_TURN_ON:
22105 5981 MONITOR_ON(monitor_id);
22106
4/6
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5967 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
5981 MONITOR_INIT(monitor_id);
22107 5981 MONITOR_SET_START(monitor_id);
22108
22109 /* If the monitor to be turned on uses
22110 existing monitor counter (status variable),
22111 make special processing to remember existing
22112 counter value. */
22113
2/2
✓ Branch 0 taken 3152 times.
✓ Branch 1 taken 2829 times.
5981 if (monitor_info->monitor_type & MONITOR_EXISTING) {
22114 3152 srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_ON);
22115 }
22116
22117
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 5792 times.
5981 if (MONITOR_IS_ON(MONITOR_LATCHES)) {
22118 189 mutex_monitor->enable();
22119 }
22120 5981 break;
22121
22122 3317 case MONITOR_TURN_OFF:
22123
2/2
✓ Branch 0 taken 988 times.
✓ Branch 1 taken 2329 times.
3317 if (monitor_info->monitor_type & MONITOR_EXISTING) {
22124 988 srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_OFF);
22125 }
22126
22127 3317 MONITOR_OFF(monitor_id);
22128 3317 MONITOR_SET_OFF(monitor_id);
22129
22130
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 2915 times.
3317 if (!MONITOR_IS_ON(MONITOR_LATCHES)) {
22131 402 mutex_monitor->disable();
22132 }
22133 3317 break;
22134
22135 42 case MONITOR_RESET_VALUE:
22136 42 srv_mon_reset(monitor_id);
22137
22138
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
42 if (monitor_id == (MONITOR_LATCHES)) {
22139 2 mutex_monitor->reset();
22140 }
22141 42 break;
22142
22143 294 case MONITOR_RESET_ALL_VALUE:
22144 294 srv_mon_reset_all(monitor_id);
22145 294 mutex_monitor->reset();
22146 294 break;
22147
22148 default:
22149 ut_error;
22150 }
22151 9634 }
22152
22153 /** Find matching InnoDB monitor counters and update their status
22154 according to the "set_option", turn on/off or reset specified
22155 monitor counter. */
22156 53 static void innodb_monitor_update_wildcard(
22157 const char *name, /*!< in: monitor name to match */
22158 mon_option_t set_option) /*!< in: the set option, whether
22159 to turn on/off or reset the counter */
22160 {
22161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 ut_a(name);
22162
22163
2/2
✓ Branch 0 taken 18126 times.
✓ Branch 1 taken 53 times.
18179 for (ulint use = 0; use < NUM_MONITOR; use++) {
22164 ulint type;
22165 18126 monitor_id_t monitor_id = static_cast<monitor_id_t>(use);
22166 monitor_info_t *monitor_info;
22167
22168
2/2
✓ Branch 0 taken 8541 times.
✓ Branch 1 taken 9585 times.
18126 if (!innobase_wildcasecmp(srv_mon_get_name(monitor_id), name)) {
22169 8541 monitor_info = srv_mon_get_info(monitor_id);
22170
22171 8541 type = monitor_info->monitor_type;
22172
22173 /* If the monitor counter is of MONITOR_MODULE
22174 type, skip it. Except for those also marked with
22175 MONITOR_GROUP_MODULE flag, which can be turned
22176 on only as a module. */
22177
4/4
✓ Branch 0 taken 8002 times.
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 7151 times.
✓ Branch 3 taken 851 times.
8541 if (!(type & MONITOR_MODULE) && !(type & MONITOR_GROUP_MODULE)) {
22178 7151 innodb_monitor_set_option(monitor_info, set_option);
22179 }
22180
22181 /* Need to special handle counters marked with
22182 MONITOR_GROUP_MODULE, turn on the whole module if
22183 any one of it comes here. Currently, only
22184 "module_buf_page" is marked with MONITOR_GROUP_MODULE */
22185
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 7667 times.
8541 if (type & MONITOR_GROUP_MODULE) {
22186
1/2
✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
874 if ((monitor_id >= MONITOR_MODULE_BUF_PAGE) &&
22187
1/2
✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
874 (monitor_id < MONITOR_MODULE_OS)) {
22188
2/2
✓ Branch 0 taken 418 times.
✓ Branch 1 taken 456 times.
874 if (set_option == MONITOR_TURN_ON &&
22189
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 11 times.
418 MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE)) {
22190 407 continue;
22191 }
22192
22193 467 srv_mon_set_module_control(MONITOR_MODULE_BUF_PAGE, set_option);
22194 } else {
22195 /* If new monitor is added with
22196 MONITOR_GROUP_MODULE, it needs
22197 to be added here. */
22198 ut_d(ut_error);
22199 }
22200 }
22201 }
22202 }
22203 53 }
22204
22205 /** Given a configuration variable name, find corresponding monitor counter
22206 and return its monitor ID if found.
22207 @return monitor ID if found, MONITOR_NO_MATCH if there is no match */
22208 5564 static ulint innodb_monitor_id_by_name_get(
22209 const char *name) /*!< in: monitor counter namer */
22210 {
22211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5564 times.
5564 ut_a(name);
22212
22213 /* Search for wild character '%' in the name, if
22214 found, we treat it as a wildcard match. We do not search for
22215 single character wildcard '_' since our monitor names already contain
22216 such character. To avoid confusion, we request user must include
22217 at least one '%' character to activate the wildcard search. */
22218
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 5453 times.
5564 if (strchr(name, '%')) {
22219 111 return (MONITOR_WILDCARD_MATCH);
22220 }
22221
22222 /* Not wildcard match, check for an exact match */
22223
2/2
✓ Branch 0 taken 924170 times.
✓ Branch 1 taken 15 times.
924185 for (ulint i = 0; i < NUM_MONITOR; i++) {
22224
2/2
✓ Branch 0 taken 5438 times.
✓ Branch 1 taken 918732 times.
924170 if (!innobase_strcasecmp(name,
22225 srv_mon_get_name(static_cast<monitor_id_t>(i)))) {
22226 5438 return (i);
22227 }
22228 }
22229
22230 15 return (MONITOR_NO_MATCH);
22231 }
22232 /** Validate that the passed in monitor name matches at least one
22233 monitor counter name with wildcard compare.
22234 @return true if at least one monitor name matches */
22235 58 static bool innodb_monitor_validate_wildcard_name(
22236 const char *name) /*!< in: monitor counter namer */
22237 {
22238
2/2
✓ Branch 0 taken 5833 times.
✓ Branch 1 taken 5 times.
5838 for (ulint i = 0; i < NUM_MONITOR; i++) {
22239
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 5780 times.
5833 if (!innobase_wildcasecmp(srv_mon_get_name(static_cast<monitor_id_t>(i)),
22240 name)) {
22241 53 return true;
22242 }
22243 }
22244
22245 5 return false;
22246 }
22247 /** Validate the passed in monitor name, find and save the
22248 corresponding monitor name in the function parameter "save".
22249 @return 0 if monitor name is valid */
22250 2792 static int innodb_monitor_valid_byname(
22251 void *save, /*!< out: immediate result
22252 for update function */
22253 const char *name) /*!< in: incoming monitor name */
22254 {
22255 ulint use;
22256 monitor_info_t *monitor_info;
22257
22258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2792 times.
2792 if (!name) {
22259 return (1);
22260 }
22261
22262 2792 use = innodb_monitor_id_by_name_get(name);
22263
22264 /* No monitor name matches, nor it is wildcard match */
22265
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2777 times.
2792 if (use == MONITOR_NO_MATCH) {
22266 15 return (1);
22267 }
22268
22269
2/2
✓ Branch 0 taken 2719 times.
✓ Branch 1 taken 58 times.
2777 if (use < NUM_MONITOR) {
22270 2719 monitor_info = srv_mon_get_info((monitor_id_t)use);
22271
22272 /* If the monitor counter is marked with
22273 MONITOR_GROUP_MODULE flag, then this counter
22274 cannot be turned on/off individually, instead
22275 it shall be turned on/off as a group using
22276 its module name */
22277
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2715 times.
2719 if ((monitor_info->monitor_type & MONITOR_GROUP_MODULE) &&
22278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 (!(monitor_info->monitor_type & MONITOR_MODULE))) {
22279 log_errlog(WARNING_LEVEL, ER_INNODB_USE_MONITOR_GROUP_NAME, name);
22280 return (1);
22281 }
22282
22283 } else {
22284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 ut_a(use == MONITOR_WILDCARD_MATCH);
22285
22286 /* For wildcard match, if there is not a single monitor
22287 counter name that matches, treat it as an invalid
22288 value for the system configuration variables */
22289
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 53 times.
58 if (!innodb_monitor_validate_wildcard_name(name)) {
22290 5 return (1);
22291 }
22292 }
22293
22294 /* Save the configure name for innodb_monitor_update() */
22295 2772 *static_cast<const char **>(save) = name;
22296
22297 2772 return (0);
22298 }
22299 /** Validate passed-in "value" is a valid monitor counter name.
22300 This function is registered as a callback with MySQL.
22301 @return 0 for valid name */
22302 2798 static int innodb_monitor_validate(
22303 THD *, /*!< in: thread handle */
22304 SYS_VAR *, /*!< in: pointer to system
22305 variable */
22306 void *save, /*!< out: immediate result
22307 for update function */
22308 struct st_mysql_value *value) /*!< in: incoming string */
22309 {
22310 const char *name;
22311 char *monitor_name;
22312 char buff[STRING_BUFFER_USUAL_SIZE];
22313 2798 int len = sizeof(buff);
22314 int ret;
22315
22316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2798 times.
2798 ut_a(save != nullptr);
22317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2798 times.
2798 ut_a(value != nullptr);
22318
22319
1/2
✓ Branch 0 taken 2798 times.
✗ Branch 1 not taken.
2798 name = value->val_str(value, buff, &len);
22320
22321
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2794 times.
2798 if (name == nullptr) {
22322 4 return (1);
22323 }
22324
22325 /* Check if the value is a valid string. */
22326 size_t valid_len;
22327 bool len_error;
22328
3/4
✓ Branch 0 taken 2794 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2790 times.
2794 if (validate_string(system_charset_info, name, len, &valid_len, &len_error)) {
22329 4 return (1);
22330 }
22331
22332 /* monitor_name could point to memory from MySQL
22333 or buff[]. Always dup the name to memory allocated
22334 by InnoDB, so we can access it in another callback
22335 function innodb_monitor_update() and free it appropriately */
22336
1/2
✓ Branch 0 taken 2790 times.
✗ Branch 1 not taken.
2790 if (name) {
22337
1/2
✓ Branch 0 taken 2790 times.
✗ Branch 1 not taken.
2790 monitor_name = my_strdup(PSI_INSTRUMENT_ME, name, MYF(0));
22338 } else {
22339 return (1);
22340 }
22341
22342
1/2
✓ Branch 0 taken 2790 times.
✗ Branch 1 not taken.
2790 ret = innodb_monitor_valid_byname(save, monitor_name);
22343
22344
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2770 times.
2790 if (ret) {
22345 /* Validation failed */
22346
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_free(monitor_name);
22347 } else {
22348 /* monitor_name will be freed in separate callback function
22349 innodb_monitor_update(). Assert "save" point to
22350 the "monitor_name" variable */
22351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2770 times.
2770 ut_ad(*static_cast<char **>(save) == monitor_name);
22352 }
22353
22354 2790 return (ret);
22355 }
22356
22357 /** Update the system variable innodb_enable(disable/reset/reset_all)_monitor
22358 according to the "set_option" and turn on/off or reset specified monitor
22359 counter. */
22360 2898 static void innodb_monitor_update(
22361 THD *thd, /*!< in: thread handle */
22362 void *var_ptr, /*!< out: where the
22363 formal string goes */
22364 const void *save, /*!< in: immediate result
22365 from check function */
22366 mon_option_t set_option, /*!< in: the set option,
22367 whether to turn on/off or
22368 reset the counter */
22369 bool free_mem) /*!< in: whether we will
22370 need to free the memory */
22371 {
22372 monitor_info_t *monitor_info;
22373 ulint monitor_id;
22374 2898 ulint err_monitor = 0;
22375 const char *name;
22376
22377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2898 times.
2898 ut_a(save != nullptr);
22378
22379 2898 name = *static_cast<const char *const *>(save);
22380
22381
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 2772 times.
2898 if (!name) {
22382 126 monitor_id = MONITOR_DEFAULT_START;
22383 } else {
22384 2772 monitor_id = innodb_monitor_id_by_name_get(name);
22385
22386 /* Double check we have a valid monitor ID */
22387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2772 times.
2772 if (monitor_id == MONITOR_NO_MATCH) {
22388 return;
22389 }
22390 }
22391
22392
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 2772 times.
2898 if (monitor_id == MONITOR_DEFAULT_START) {
22393 /* If user set the variable to "default", we will
22394 print a message and make this set operation a "noop".
22395 The check is being made here is because "set default"
22396 does not go through validation function */
22397
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 if (thd) {
22398 126 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_DEFAULT,
22399 "Default value is not defined for"
22400 " this set option. Please specify"
22401 " correct counter or module name.");
22402 } else {
22403 log_errlog(ERROR_LEVEL, ER_INNODB_MONITOR_DEFAULT_VALUE_NOT_DEFINED);
22404 }
22405
22406
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 if (var_ptr) {
22407 126 *(const char **)var_ptr = nullptr;
22408 }
22409
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2719 times.
2772 } else if (monitor_id == MONITOR_WILDCARD_MATCH) {
22410 53 innodb_monitor_update_wildcard(name, set_option);
22411 } else {
22412 2719 monitor_info = srv_mon_get_info(static_cast<monitor_id_t>(monitor_id));
22413
22414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2719 times.
2719 ut_a(monitor_info);
22415
22416 /* If monitor is already truned on, someone could already
22417 collect monitor data, exit and ask user to turn off the
22418 monitor before turn it on again. */
22419
4/4
✓ Branch 0 taken 2431 times.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2427 times.
2719 if (set_option == MONITOR_TURN_ON && MONITOR_IS_ON(monitor_id)) {
22420 4 err_monitor = monitor_id;
22421 4 goto exit;
22422 }
22423
22424
2/2
✓ Branch 0 taken 2713 times.
✓ Branch 1 taken 2 times.
2715 if (var_ptr) {
22425 2713 *(const char **)var_ptr = monitor_info->monitor_name;
22426 }
22427
22428 /* Depending on the monitor name is for a module or
22429 a counter, process counters in the whole module or
22430 individual counter. */
22431
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 2483 times.
2715 if (monitor_info->monitor_type & MONITOR_MODULE) {
22432 232 srv_mon_set_module_control(static_cast<monitor_id_t>(monitor_id),
22433 set_option);
22434 } else {
22435 2483 innodb_monitor_set_option(monitor_info, set_option);
22436 }
22437 }
22438 2898 exit:
22439 /* Only if we are trying to turn on a monitor that already
22440 been turned on, we will set err_monitor. Print related
22441 information */
22442
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2894 times.
2898 if (err_monitor) {
22443 4 log_errlog(WARNING_LEVEL, ER_INNODB_MONITOR_IS_ENABLED,
22444 srv_mon_get_name((monitor_id_t)err_monitor));
22445 }
22446
22447
4/4
✓ Branch 0 taken 2896 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2770 times.
✓ Branch 3 taken 126 times.
2898 if (free_mem && name) {
22448 2770 my_free((void *)name);
22449 }
22450
22451 2898 return;
22452 }
22453
22454 /** Validate if passed-in "value" is a valid value for
22455 innodb_buffer_pool_filename. On Windows, file names with colon (:)
22456 are not allowed.
22457 @param[in] thd thread handle
22458 @param[in] save immediate result from update function
22459 @param[in] value incoming string
22460 @return 0 for valid name */
22461 9 static int innodb_srv_buf_dump_filename_validate(THD *thd, SYS_VAR *,
22462 void *save,
22463 struct st_mysql_value *value) {
22464 char buff[OS_FILE_MAX_PATH];
22465 9 int len = sizeof(buff);
22466
22467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(save != nullptr);
22468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(value != nullptr);
22469
22470
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 const char *buf_name = value->val_str(value, buff, &len);
22471
22472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (buf_name == nullptr) {
22473 return (1);
22474 }
22475
22476
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (buf_name == buff) {
22477 /* Allocate from thd's memroot */
22478
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 buf_name = thd_strmake(thd, buf_name, len);
22479 }
22480
22481 #ifdef _WIN32
22482 if (is_filename_allowed(buf_name, len, false)) {
22483 *static_cast<const char **>(save) = buf_name;
22484 return (0);
22485 } else {
22486 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22487 "InnoDB: innodb_buffer_pool_filename"
22488 " cannot have colon (:) in the file name.");
22489 return (1);
22490 }
22491 #else /* _WIN32 */
22492 9 *static_cast<const char **>(save) = buf_name;
22493 9 return (0);
22494 #endif
22495 }
22496
22497 #ifdef UNIV_DEBUG
22498 static char *srv_buffer_pool_evict;
22499
22500 /** Evict all uncompressed pages of compressed tables from the buffer pool.
22501 Keep the compressed pages in the buffer pool.
22502 @return whether all uncompressed pages were evicted */
22503 4 [[nodiscard]] static bool innodb_buffer_pool_evict_uncompressed(void) {
22504 4 bool all_evicted = true;
22505
22506
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
22507 4 buf_pool_t *buf_pool = &buf_pool_ptr[i];
22508
22509 4 mutex_enter(&buf_pool->LRU_list_mutex);
22510
22511 4 for (buf_block_t *block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
22512
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4 times.
19 block != nullptr;) {
22513 15 buf_block_t *prev_block = UT_LIST_GET_PREV(unzip_LRU, block);
22514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
22515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 ut_ad(block->in_unzip_LRU_list);
22516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 ut_ad(block->page.in_LRU_list);
22517
22518 15 mutex_enter(&block->mutex);
22519
22520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!buf_LRU_free_page(&block->page, false)) {
22521 mutex_exit(&block->mutex);
22522 all_evicted = false;
22523 } else {
22524 /* buf_LRU_free_page() released LRU_list_mutex.
22525 have to restart the unzip_LRU scan. */
22526 15 mutex_enter(&buf_pool->LRU_list_mutex);
22527 15 block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
22528 15 continue;
22529 }
22530 block = prev_block;
22531 }
22532
22533 4 mutex_exit(&buf_pool->LRU_list_mutex);
22534 }
22535
22536 4 return (all_evicted);
22537 }
22538
22539 /** Called on SET GLOBAL innodb_buffer_pool_evict=...
22540 Handles some values specially, to evict pages from the buffer pool.
22541 SET GLOBAL innodb_buffer_pool_evict='uncompressed'
22542 evicts all uncompressed page frames of compressed tablespaces.
22543 @param[in] save immediate result from check function */
22544 8 static void innodb_buffer_pool_evict_update(THD *, SYS_VAR *, void *,
22545 const void *save) {
22546
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if (const char *op = *static_cast<const char *const *>(save)) {
22547
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
7 if (!strcmp(op, "uncompressed")) {
22548
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 for (uint tries = 0; tries < 10000; tries++) {
22549
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (innodb_buffer_pool_evict_uncompressed()) {
22550 4 return;
22551 }
22552
22553 std::this_thread::sleep_for(std::chrono::milliseconds(10));
22554 }
22555
22556 /* We failed to evict all uncompressed pages. */
22557 ut_d(ut_error);
22558 }
22559 }
22560 }
22561 #endif /* UNIV_DEBUG */
22562
22563 /** Update the system variable innodb_monitor_enable and enable
22564 specified monitor counter.
22565 This function is registered as a callback with MySQL.
22566 @param[in] thd thread handle
22567 @param[out] var_ptr where the formal string goes
22568 @param[in] save immediate result from check function */
22569 2496 static void innodb_enable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
22570 const void *save) {
22571 2496 innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON, true);
22572 2496 }
22573
22574 /** Update the system variable innodb_monitor_disable and turn
22575 off specified monitor counter.
22576 @param[in] thd thread handle
22577 @param[out] var_ptr where the formal string goes
22578 @param[in] save immediate result from check function */
22579 182 static void innodb_disable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
22580 const void *save) {
22581 182 innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF, true);
22582 182 }
22583
22584 /** Update the system variable innodb_monitor_reset and reset
22585 specified monitor counter(s).
22586 This function is registered as a callback with MySQL.
22587 @param[in] thd thread handle
22588 @param[out] var_ptr where the formal string goes
22589 @param[in] save immediate result from check function */
22590 125 static void innodb_reset_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
22591 const void *save) {
22592 125 innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE, true);
22593 125 }
22594
22595 /** Update the system variable innodb_monitor_reset_all and reset
22596 all value related monitor counter.
22597 This function is registered as a callback with MySQL.
22598 @param[in] thd thread handle
22599 @param[out] var_ptr where the formal string goes
22600 @param[in] save immediate result from check function */
22601 93 static void innodb_reset_all_monitor_update(THD *thd, SYS_VAR *, void *var_ptr,
22602 const void *save) {
22603 93 innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE, true);
22604 93 }
22605
22606 /** Validate the value of innodb_undo_tablespaces global variable. This function
22607 is registered as a callback with MySQL.
22608 @param[in] thd thread handle
22609 @param[in] var pointer to system variable
22610 @param[in] var_ptr where the formal string goes
22611 @param[in] save immediate result from check function */
22612 6 static void innodb_undo_tablespaces_update(THD *thd [[maybe_unused]],
22613 SYS_VAR *var [[maybe_unused]],
22614 void *var_ptr [[maybe_unused]],
22615 const void *save [[maybe_unused]]) {
22616 6 innodb_undo_tablespaces_deprecate();
22617 6 }
22618
22619 /** Validate the value of innodb_parallel_doublewrite_path global variable.
22620 This function is registered as a callback with MySQL.
22621 @param[in] thd thread handle
22622 @param[in] var pointer to system variable
22623 @param[in] var_ptr where the formal string goes
22624 @param[in] save immediate result from check function */
22625 static void innodb_parallel_doublewrite_path_update(
22626 THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]],
22627 void *var_ptr [[maybe_unused]],
22628 const void *save [[maybe_unused]]) {
22629 innodb_parallel_doublewrite_path_deprecate();
22630 }
22631
22632 /** Validate the value of innodb_parallel_dblwr_encrypt global variable.
22633 This function is registered as a callback with MySQL.
22634 @param[in] thd thread handle
22635 @param[in] var pointer to system variable
22636 @param[in] var_ptr where the formal string goes
22637 @param[in] save immediate result from check function */
22638 3 static void innodb_parallel_dblwr_encrypt_update(
22639 THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]],
22640 void *var_ptr [[maybe_unused]],
22641 const void *save [[maybe_unused]]) {
22642 3 innodb_parallel_dblwr_encrypt_deprecate();
22643 3 }
22644
22645 /* Declare default check function for boolean system variable. Cannot include
22646 sql_plugin_var.h header in this file due to conflicting macro definitions. */
22647 int check_func_bool(THD *, SYS_VAR *, void *save, st_mysql_value *value);
22648
22649 /** Validate the value of innodb_undo_log_encrypt global variable. This function
22650 is registered as a callback with MySQL.
22651 @param[in] thd thread handle
22652 @param[in] var pointer to system variable
22653 @param[in] save possibly updated variable value
22654 @param[in] value current variable value
22655 @return error code */
22656 86 static int validate_innodb_undo_log_encrypt(THD *thd, SYS_VAR *var, void *save,
22657 struct st_mysql_value *value) {
22658 /* Call the default check function first. */
22659 86 auto error = check_func_bool(thd, var, save, value);
22660
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 83 times.
86 if (error != 0) {
22661 3 return (error);
22662 }
22663 83 bool target = *static_cast<bool *>(save);
22664
22665 /* Set the default output to current value for all error cases. */
22666 83 *static_cast<bool *>(save) = srv_undo_log_encrypt;
22667
22668
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 54 times.
83 if (srv_undo_log_encrypt == target) {
22669 /* No change */
22670 29 return (0);
22671 }
22672
22673
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 13 times.
54 if (target) {
22674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (Encryption::is_online_encryption_on()) {
22675 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22676 "Undo log cannot be"
22677 " encrypted with Master Key encryption"
22678 " when online to KEYRING encryption is turned ON.");
22679 return 1;
22680 }
22681 }
22682
22683 /* If encryption is to be disabled. This will just make sure I/O doesn't
22684 write UNDO pages encrypted from now on. */
22685
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 41 times.
54 if (target == false) {
22686 13 *static_cast<bool *>(save) = false;
22687 13 return (0);
22688 }
22689
22690 /* There would be at least 2 UNDO tablespaces */
22691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES);
22692
22693
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 36 times.
41 if (!Encryption::check_keyring()) {
22694 5 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_DA_UNDO_NO_KEYRING);
22695 5 ib::error(ER_UNDO_NO_KEYRING);
22696 5 return (0);
22697 }
22698
22699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (srv_read_only_mode) {
22700 ib::error(ER_IB_MSG_1051);
22701 ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_IB_MSG_1051);
22702 return (0);
22703 }
22704
22705 /* UNDO tablespace encryption to be mutually exclusive with any UNDO DDL */
22706 36 mutex_enter(&undo::ddl_mutex);
22707
22708 /* Enable encryption for UNDO tablespaces */
22709 36 bool ret = srv_enable_undo_encryption(nullptr);
22710
22711
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
36 if (!ret) {
22712 /* At this point, all UNDO tablespaces have been encrypted. */
22713 34 *static_cast<bool *>(save) = true;
22714 }
22715
22716 36 mutex_exit(&undo::ddl_mutex);
22717 36 return (0);
22718 }
22719
22720 /** Validate the value of innodb_redo_log_encrypt global variable. This function
22721 is registered as a callback with MySQL.
22722 @param[in] thd thread handle
22723 @param[in] var pointer to system variable
22724 @param[in] save possibly updated variable value
22725 @param[in] value current variable value
22726 @return error code */
22727 90 static int validate_innodb_redo_log_encrypt(THD *thd, SYS_VAR *var, void *save,
22728 struct st_mysql_value *value) {
22729 /* Call the default check function first. */
22730 90 auto error = check_func_bool(thd, var, save, value);
22731
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 87 times.
90 if (error != 0) {
22732 3 return (error);
22733 }
22734 87 bool target = *static_cast<bool *>(save);
22735
22736 /* Set the default output to current value for all error cases. */
22737 87 *static_cast<bool *>(save) = srv_redo_log_encrypt;
22738
22739
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 47 times.
87 if (srv_redo_log_encrypt == target) {
22740 /* No change */
22741 40 return (0);
22742 }
22743
22744 /* If encryption is to be disabled. This will just make sure I/O doesn't
22745 write REDO encrypted from now on. */
22746
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 34 times.
47 if (target == false) {
22747 13 *static_cast<bool *>(save) = false;
22748 13 return (0);
22749 }
22750
22751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (srv_read_only_mode) {
22752 ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY);
22753 return (0);
22754 }
22755
22756 /* Enable encryption for REDO tablespaces */
22757 34 bool ret = srv_enable_redo_encryption();
22758
22759
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 7 times.
34 if (!ret) {
22760 /* At this point, REDO log is set to be encrypted. */
22761 27 *static_cast<bool *>(save) = true;
22762 }
22763 34 return (0);
22764 }
22765
22766 9 static int innodb_sys_tablespace_encyption_validate(
22767 THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) {
22768 const char *innodb_sys_tablespace_encryption_input;
22769 char buff[STRING_BUFFER_USUAL_SIZE];
22770 9 int len = sizeof(buff);
22771
22772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(save != nullptr);
22773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 ut_a(value != nullptr);
22774
22775
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 innodb_sys_tablespace_encryption_input = value->val_str(value, buff, &len);
22776
22777 9 bool legit_value = false;
22778 9 uint use = 0;
22779 // The last item of sys_tablespace_encrypt_names is nullptr
22780 9 const size_t encrypt_names_cnt =
22781 array_elements(sys_tablespace_encrypt_names) - 1;
22782
22783
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5 times.
27 for (; use < encrypt_names_cnt; use++) {
22784
3/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 18 times.
22 if (!innobase_strcasecmp(innodb_sys_tablespace_encryption_input,
22785 sys_tablespace_encrypt_names[use])) {
22786 4 legit_value = true;
22787 4 break;
22788 }
22789 }
22790 // It is possible that enum value was provided as the integer, not literal
22791
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (!legit_value) {
22792 5 int error = 0;
22793
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 use = (uint)my_strtoll10(innodb_sys_tablespace_encryption_input, nullptr,
22794 &error);
22795
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
5 if (!error && use < encrypt_names_cnt) {
22796 2 legit_value = true;
22797 }
22798 }
22799
22800
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 if (!legit_value) return 1;
22801
22802 6 const auto change_to_sys_tablespace_encryption =
22803 static_cast<srv_sys_tablespace_encrypt_enum>(use);
22804
22805
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_OFF) {
22806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_ON) {
22807 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22808 "System tablespace Master Key encryption cannot be "
22809 "turned OFF dynamically. "
22810 "However you can still re-encrypt system tablespace "
22811 "with encryption threads "
22812 "and then instruct encryption threads to decrypt the "
22813 "system tablespace.");
22814 return 1;
22815 }
22816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) {
22817 push_warning_printf(
22818 thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22819 "RE_ENCRYPTING_TO_KEYRING can be only used when system tablespace "
22820 "was previously encrypted with Master Key encryption. To encrypt "
22821 "system tablespace with KEYRING encryption please use encryption "
22822 "threads.");
22823 return 1;
22824 }
22825 }
22826
22827
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_ON) {
22828
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) {
22829
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 push_warning_printf(
22830 thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22831 "System tablespace Master Key encryption can be turned ON only "
22832 "at bootstrap. You can still encrypt System tablespace encryption "
22833 "with "
22834 "KEYRING encryption.");
22835 2 return 1;
22836 } else if (srv_sys_tablespace_encrypt ==
22837 SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) {
22838 // The system tablespace encryption was marked to be re-encrypted to
22839 // keyring. We allow it to be set back to ON in case encryption threads
22840 // were not yet activated and system tablespace remain encrypted with
22841 // Master Key.
22842 if (Encryption::is_online_encryption_on()) {
22843 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22844 "System tablespace cannot be marked as encrypted "
22845 "with Master Key encryption "
22846 "when Online to keyring encryption is turned ON or "
22847 "when system tablespace "
22848 "was already encrypted with KEYRING encryption.");
22849 return 1;
22850 } else {
22851 fil_space_t *space = fil_space_acquire_silent(TRX_SYS_SPACE);
22852 ut_ad(space != nullptr);
22853 fil_space_crypt_t *crypt_data = space->crypt_data;
22854 fil_space_release(space);
22855
22856 if (crypt_data != nullptr) {
22857 push_warning_printf(thd, Sql_condition::SL_WARNING,
22858 ER_WRONG_ARGUMENTS,
22859 "System tablespace cannot be marked as encrypted "
22860 "with Master Key encryption "
22861 "as it was already encrypted with KEYRING "
22862 "encryption and Master Key encryption "
22863 "is bootstrap only option.");
22864 return 1;
22865 }
22866 }
22867 }
22868 }
22869
22870
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (change_to_sys_tablespace_encryption ==
22871 1 SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING &&
22872
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) {
22873
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 push_warning_printf(
22874 thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22875 "System tablespace can only be marked to be re-encrypted with keyring "
22876 "in "
22877 "case it was previosly encrypted with Master Key encryption. "
22878 "You still can encrypt unencrypted system tablespace with encryption "
22879 "threads.");
22880 1 return 1;
22881 }
22882
22883 3 *static_cast<ulong *>(save) = use;
22884
22885 3 return 0;
22886 }
22887
22888 /** Update the number of rollback segments per tablespace when the
22889 system variable innodb_rollback_segments is changed.
22890 This function is registered as a callback with MySQL.
22891 @param[in] save immediate result from check function */
22892 22 static void innodb_rollback_segments_update(THD *, SYS_VAR *, void *,
22893 const void *save) {
22894 22 ulong target = *static_cast<const ulong *>(save);
22895
22896
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 15 times.
22 if (srv_rollback_segments == target) {
22897 11 return;
22898 }
22899
22900
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
15 if (srv_read_only_mode) {
22901
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 ib::warn(ER_IB_MSG_578) << "Cannot set innodb_rollback_segments to "
22902
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 << target << " when in read-only mode";
22903 2 return;
22904 }
22905
22906
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (srv_force_recovery > 0) {
22907
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 ib::warn(ER_IB_MSG_579) << "Cannot set innodb_rollback_segments to "
22908
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 << target << " when in innodb_force_recovery > 0";
22909 2 return;
22910 }
22911
22912 /* Serialize this adjustment with all undo tablespace DDLs. */
22913
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mutex_enter(&undo::ddl_mutex);
22914
22915
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (!trx_rseg_adjust_rollback_segments(target)) {
22916 ib::warn(ER_IB_MSG_580)
22917 << "Failed to set innodb_rollback_segments to " << target;
22918 return;
22919 }
22920
22921 11 srv_rollback_segments = target;
22922
22923
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mutex_exit(&undo::ddl_mutex);
22924 }
22925
22926 /** Parse and enable InnoDB monitor counters during server startup.
22927 User can list the monitor counters/groups to be enable by specifying
22928 "loose-innodb_monitor_enable=monitor_name1;monitor_name2..."
22929 in server configuration file or at the command line. The string
22930 separate could be ";", "," or empty space. */
22931 2 static void innodb_enable_monitor_at_startup(
22932 char *str) /*!< in/out: monitor counter enable list */
22933 {
22934 static const char *sep = " ;,";
22935 char *last;
22936
22937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ut_a(str);
22938
22939 /* Walk through the string, and separate each monitor counter
22940 and/or counter group name, and calling innodb_monitor_update()
22941 if successfully updated. Please note that the "str" would be
22942 changed by strtok_r() as it walks through it. */
22943
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (char *option = my_strtok_r(str, sep, &last); option;
22944 2 option = my_strtok_r(nullptr, sep, &last)) {
22945 ulint ret;
22946 char *option_name;
22947
22948
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ret = innodb_monitor_valid_byname(&option_name, option);
22949
22950 /* The name is validated if ret == 0 */
22951
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!ret) {
22952
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 innodb_monitor_update(nullptr, nullptr, &option, MONITOR_TURN_ON, false);
22953 } else {
22954 log_errlog(WARNING_LEVEL, ER_INNODB_INVALID_MONITOR_COUNTER_NAME, option);
22955 }
22956 }
22957 2 }
22958
22959 #if defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || defined(UNIV_PERF_DEBUG))
22960
22961 /** Update the innodb_sched_priority_purge variable and set the thread
22962 priorities accordingly.
22963 @param[in] thd thread handle
22964 @param[in] var pointer to system variable
22965 @param[out] var_ptr where the formal string goes
22966 @param[in] save immediate result from check function */
22967 8 static void innodb_sched_priority_purge_update(THD *thd, SYS_VAR *var,
22968 void *var_ptr,
22969 const void *save) {
22970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (srv_read_only_mode) return;
22971
22972 8 const ulint priority = *static_cast<const ulint *>(save);
22973
22974
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
40 for (ulint i = 0; i < srv_n_purge_threads; i++) {
22975 const ulint actual_priority =
22976 32 os_thread_set_priority(srv_purge_tids[i], priority);
22977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (UNIV_UNLIKELY(actual_priority != priority)) {
22978 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
22979 "Failed to set the purge thread priority to %lu, "
22980 "the current priority is %lu, aborting priority "
22981 "update",
22982 priority, actual_priority);
22983 return;
22984 }
22985 }
22986
22987 8 srv_sched_priority_purge = priority;
22988 }
22989
22990 /** Update the innodb_sched_priority_io variable and set the thread priorities
22991 accordingly.
22992 @param[in] thd thread handle
22993 @param[in] var pointer to system variable
22994 @param[out] var_ptr where the formal string goes
22995 @param[in] save immediate result from check function */
22996 7 static void innodb_sched_priority_io_update(THD *thd, SYS_VAR *var,
22997 void *var_ptr, const void *save) {
22998 7 const ulint priority = *static_cast<const ulint *>(save);
22999
23000
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 7 times.
77 for (ulint i = 0; i < srv_n_file_io_threads; i++) {
23001 const ulint actual_priority =
23002 70 os_thread_set_priority(srv_io_tids[i], priority);
23003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 if (UNIV_UNLIKELY(actual_priority != priority)) {
23004 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23005 "Failed to set the I/O thread priority to %lu, the "
23006 "current priority is %lu, aborting priority update",
23007 priority, actual_priority);
23008 return;
23009 }
23010 }
23011 7 srv_sched_priority_io = priority;
23012 }
23013
23014 /** Update the innodb_sched_priority_master variable and set the thread
23015 priorities accordingly.
23016 @param[in] thd thread handle
23017 @param[in] var pointer to system variable
23018 @param[out] var_ptr where the formal string goes
23019 @param[in] save immediate result from check function */
23020 7 static void innodb_sched_priority_master_update(THD *thd, SYS_VAR *var,
23021 void *var_ptr,
23022 const void *save) {
23023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (srv_read_only_mode) return;
23024
23025 7 const ulint priority = *static_cast<const lint *>(save);
23026 const ulint actual_priority =
23027 7 os_thread_set_priority(srv_master_tid, priority);
23028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (UNIV_UNLIKELY(actual_priority != priority)) {
23029 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23030 "Failed to set the master thread priority to %lu, the "
23031 "current priority is %lu",
23032 priority, actual_priority);
23033 } else {
23034 7 srv_sched_priority_master = priority;
23035 }
23036 }
23037
23038 #endif /* defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || \
23039 defined(UNIV_PERF_DEBUG)) */
23040
23041 /** Callback function for accessing the InnoDB variables from MySQL:
23042 SHOW VARIABLES. */
23043 107956 static int show_innodb_vars(THD *, SHOW_VAR *var, char *) {
23044 107956 innodb_export_status();
23045 107953 var->type = SHOW_ARRAY;
23046 107953 var->value = (char *)&innodb_status_variables;
23047 107953 var->scope = SHOW_SCOPE_GLOBAL;
23048
23049 107953 return (0);
23050 }
23051
23052 /** This function checks each index name for a table against reserved
23053 system default primary index name 'GEN_CLUST_INDEX'. If a name
23054 matches, this function pushes an warning message to the client,
23055 and returns true.
23056 @return true if the index name matches the reserved name */
23057 458569 bool innobase_index_name_is_reserved(
23058 THD *thd, /*!< in/out: MySQL connection */
23059 const KEY *key_info, /*!< in: Indexes to be created */
23060 ulint num_of_keys) /*!< in: Number of indexes to
23061 be created. */
23062 {
23063 const KEY *key;
23064 uint key_num; /* index number */
23065
23066
2/2
✓ Branch 0 taken 231907 times.
✓ Branch 1 taken 458566 times.
690473 for (key_num = 0; key_num < num_of_keys; key_num++) {
23067 231907 key = &key_info[key_num];
23068
23069
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 231904 times.
231907 if (innobase_strcasecmp(key->name, innobase_index_reserve_name) == 0) {
23070 /* Push warning to mysql */
23071 3 push_warning_printf(thd, Sql_condition::SL_WARNING,
23072 ER_WRONG_NAME_FOR_INDEX,
23073 "Cannot Create Index with name"
23074 " '%s'. The name is reserved"
23075 " for the system default primary"
23076 " index.",
23077 innobase_index_reserve_name);
23078
23079 3 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), innobase_index_reserve_name);
23080
23081 3 return (true);
23082 }
23083 }
23084
23085 458566 return (false);
23086 }
23087
23088 /** Retrieve the FTS Relevance Ranking result for doc with doc_id
23089 of m_prebuilt->fts_doc_id
23090 @param[in,out] fts_hdl FTS handler
23091 @return the relevance ranking value */
23092 2962 static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl) {
23093 fts_result_t *result;
23094 row_prebuilt_t *ft_prebuilt [[maybe_unused]];
23095
23096 2962 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
23097
23098 2962 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt;
23099
23100 2962 fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
23101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2962 times.
2962 assert(ft_prebuilt->fts_doc_id == ranking->doc_id);
23102
23103 2962 return (ranking->rank);
23104 }
23105
23106 /** Free the memory for the FTS handler
23107 @param[in,out] fts_hdl FTS handler */
23108 2283 static void innobase_fts_close_ranking(FT_INFO *fts_hdl) {
23109 fts_result_t *result;
23110
23111 2283 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
23112
23113 2283 fts_query_free_result(result);
23114
23115 2283 my_free((uchar *)fts_hdl);
23116 2283 }
23117
23118 /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id
23119 of m_prebuilt->fts_doc_id
23120 @param[in,out] fts_hdl FTS handler
23121 @return the relevance ranking value */
23122 5656 static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint) {
23123 fts_result_t *result;
23124 row_prebuilt_t *ft_prebuilt;
23125
23126 5656 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt;
23127 5656 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
23128
23129 /* Retrieve the ranking value for doc_id with value of
23130 m_prebuilt->fts_doc_id */
23131 5656 return (fts_retrieve_ranking(result, ft_prebuilt->fts_doc_id));
23132 }
23133
23134 #ifdef UNIV_DEBUG
23135 static bool innodb_background_drop_list_empty = true;
23136 static bool innodb_purge_run_now = true;
23137 static bool innodb_purge_stop_now = true;
23138 static bool innodb_log_checkpoint_now = true;
23139 static bool innodb_log_checkpoint_fuzzy_now = true;
23140 static bool innodb_log_flush_now = true;
23141 static bool innodb_buf_flush_list_now = true;
23142
23143 static uint innodb_merge_threshold_set_all_debug =
23144 DICT_INDEX_MERGE_THRESHOLD_DEFAULT;
23145
23146 /** Wait for the background drop list to become empty. */
23147 4 static void wait_background_drop_list_empty(THD *, SYS_VAR *, void *,
23148 const void *) {
23149 4 row_wait_for_background_drop_list_empty();
23150 4 }
23151
23152 /** Set the purge state to RUN. If purge is disabled then it
23153 is a no-op. This function is registered as a callback with MySQL.
23154 @param[in] save immediate result from check function */
23155 464 static void purge_run_now_set(THD *, SYS_VAR *, void *, const void *save) {
23156
5/6
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 461 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 461 times.
✓ Branch 5 taken 3 times.
464 if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) {
23157 461 trx_purge_run();
23158 }
23159 464 }
23160
23161 /** Set the purge state to STOP. If purge is disabled then it
23162 is a no-op. This function is registered as a callback with MySQL.
23163 @param[in] save immediate result from check function */
23164 102 static void purge_stop_now_set(THD *, SYS_VAR *, void *, const void *save) {
23165
5/6
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
✓ Branch 5 taken 5 times.
102 if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) {
23166 97 trx_purge_stop();
23167 }
23168 102 }
23169
23170 /** Force InnoDB to flush redo log up to current_lsn.
23171 This function is registered as a callback with MySQL.
23172 @param[in] save immediate result from check function */
23173 8 static void log_flush_now_set(THD *, SYS_VAR *, void *, const void *save) {
23174
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (!*(bool *)save) {
23175 6 return;
23176 }
23177
23178 2 log_buffer_flush_to_disk(true);
23179 }
23180
23181 /** Force InnoDB to do sharp checkpoint. This forces a flush of all
23182 dirty pages.
23183 @param[in] save immediate result from check function */
23184 31 static void checkpoint_now_set(THD *, SYS_VAR *, void *, const void *save) {
23185
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
31 if (*(bool *)save && !srv_checkpoint_disabled) {
23186 /* Note that it's defined only when UNIV_DEBUG is defined.
23187 It seems to be very risky feature. Fortunately it is used
23188 only inside mtr tests. */
23189
23190
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 24 times.
73 while (log_make_latest_checkpoint(*log_sys)) {
23191 /* Creating checkpoint could itself result in
23192 new log records. Hence we repeat until:
23193 last_checkpoint_lsn = log_get_lsn(). */
23194 }
23195
23196 48 dberr_t err = fil_write_flushed_lsn(log_sys->last_checkpoint_lsn.load());
23197
23198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 ut_a(err == DB_SUCCESS);
23199 }
23200 31 }
23201
23202 /** Force InnoDB to do fuzzy checkpoint. Fuzzy checkpoint does not
23203 force InnoDB to flush dirty pages. It only forces to write the new
23204 checkpoint_lsn to the header of the log file containing that LSN.
23205 This LSN is where the recovery starts. You can read more about the
23206 fuzzy checkpoints in the internet.
23207 @param[in] save immediate result from check function */
23208 8 static void checkpoint_fuzzy_now_set(THD *, SYS_VAR *, void *,
23209 const void *save) {
23210
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
8 if (*(bool *)save && !srv_checkpoint_disabled) {
23211 /* Note that it's defined only when UNIV_DEBUG is defined.
23212 It seems to be very risky feature. Fortunately it is used
23213 only inside mtr tests. */
23214
23215 2 log_request_checkpoint(*log_sys, true);
23216 }
23217 8 }
23218
23219 /** Updates srv_checkpoint_disabled - allowing or disallowing checkpoints.
23220 This is called when user invokes SET GLOBAL innodb_checkpoints_disabled=0/1.
23221 After checkpoints are disabled, there will be no write of a checkpoint,
23222 until checkpoints are re-enabled (log_sys->checkpointer_mutex protects that)
23223 @param[in] save immediate result from check function */
23224 94 static void checkpoint_disabled_update(THD *, SYS_VAR *, void *,
23225 const void *save) {
23226 /* We need to acquire the checkpointer_mutex, to ensure that
23227 after we have finished this function, there will be no new
23228 checkpoint written (e.g. in case there is currently curring
23229 checkpoint). When checkpoint is being written, the same mutex
23230 is acquired, current value of srv_checkpoint_disabled is checked,
23231 and if checkpoints are disabled, we cancel writing the checkpoint. */
23232
23233 94 log_t &log = *log_sys;
23234
23235 94 log_checkpointer_mutex_enter(log);
23236 94 log_limits_mutex_enter(log);
23237
23238 94 srv_checkpoint_disabled = *static_cast<const bool *>(save);
23239
23240 94 log_limits_mutex_exit(log);
23241 94 log_checkpointer_mutex_exit(log);
23242 94 }
23243
23244 /** Force a dirty pages flush now.
23245 @param[in] save immediate result from check function */
23246 218 static void buf_flush_list_now_set(THD *, SYS_VAR *, void *, const void *save) {
23247
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 5 times.
218 if (*(bool *)save) {
23248 213 buf_flush_sync_all_buf_pools();
23249 }
23250 218 }
23251
23252 /** Override current MERGE_THRESHOLD setting for all indexes at dictionary
23253 now.
23254 @param[in] save immediate result from check function */
23255 7 static void innodb_merge_threshold_set_all_debug_update(THD *, SYS_VAR *,
23256 void *,
23257 const void *save) {
23258 7 innodb_merge_threshold_set_all_debug = (*static_cast<const uint *>(save));
23259 7 dict_set_merge_threshold_all_debug(innodb_merge_threshold_set_all_debug);
23260 7 }
23261
23262 #endif /* UNIV_DEBUG */
23263
23264 /** Find and Retrieve the FTS doc_id for the current result row
23265 @param[in,out] fts_hdl FTS handler
23266 @return the document ID */
23267 static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl) {
23268 fts_result_t *result;
23269 row_prebuilt_t *ft_prebuilt;
23270
23271 ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt;
23272 result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result;
23273
23274 if (ft_prebuilt->read_just_key) {
23275 fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current);
23276
23277 return (ranking->doc_id);
23278 }
23279
23280 return (ft_prebuilt->fts_doc_id);
23281 }
23282
23283 /* These variables are never read by InnoDB or changed. They are a kind of
23284 dummies that are needed by the MySQL infrastructure to call
23285 buffer_pool_dump_now(), buffer_pool_load_now() and buffer_pool_load_abort()
23286 by the user by doing:
23287 SET GLOBAL innodb_buffer_pool_dump_now=ON;
23288 SET GLOBAL innodb_buffer_pool_load_now=ON;
23289 SET GLOBAL innodb_buffer_pool_load_abort=ON;
23290 Their values are read by MySQL and displayed to the user when the variables
23291 are queried, e.g.:
23292 SELECT @@innodb_buffer_pool_dump_now;
23293 SELECT @@innodb_buffer_pool_load_now;
23294 SELECT @@innodb_buffer_pool_load_abort; */
23295 static bool innodb_buffer_pool_dump_now = false;
23296 static bool innodb_buffer_pool_load_now = false;
23297 static bool innodb_buffer_pool_load_abort = false;
23298
23299 /** Trigger a dump of the buffer pool if innodb_buffer_pool_dump_now is set
23300 to ON. This function is registered as a callback with MySQL.
23301 @param[in] save immediate result from check function */
23302 10 static void buffer_pool_dump_now(THD *, SYS_VAR *, void *, const void *save) {
23303
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
10 if (*(bool *)save && !srv_read_only_mode) {
23304 7 buf_dump_start();
23305 }
23306 10 }
23307
23308 /** Trigger a load of the buffer pool if innodb_buffer_pool_load_now is set
23309 to ON. This function is registered as a callback with MySQL.
23310 @param[in] save immediate result from check function */
23311 9 static void buffer_pool_load_now(THD *, SYS_VAR *, void *, const void *save) {
23312
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 if (*(bool *)save) {
23313 6 buf_load_start();
23314 }
23315 9 }
23316
23317 /** Abort a load of the buffer pool if innodb_buffer_pool_load_abort
23318 is set to ON. This function is registered as a callback with MySQL.
23319 @param[in] save immediate result from check function */
23320 4 static void buffer_pool_load_abort(THD *, SYS_VAR *, void *, const void *save) {
23321
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (*(bool *)save) {
23322 1 buf_load_abort();
23323 }
23324 4 }
23325
23326 /** Update the system variable innodb_log_write_ahead_size using the "saved"
23327 value. This function is registered as a callback with MySQL.
23328 @param[in] thd thread handle
23329 @param[in] save immediate result from check function */
23330 163 static void innodb_log_write_ahead_size_update(THD *thd, SYS_VAR *, void *,
23331 const void *save) {
23332 163 ulong val = INNODB_LOG_WRITE_AHEAD_SIZE_MIN;
23333 163 ulong in_val = *static_cast<const ulong *>(save);
23334
23335
2/2
✓ Branch 0 taken 412 times.
✓ Branch 1 taken 163 times.
575 while (val < in_val) {
23336 412 val = val * 2;
23337 }
23338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
163 if (val > INNODB_LOG_WRITE_AHEAD_SIZE_MAX) {
23339 val = INNODB_LOG_WRITE_AHEAD_SIZE_MAX;
23340 }
23341
23342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
163 if (val > UNIV_PAGE_SIZE) {
23343 val = UNIV_PAGE_SIZE;
23344 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23345 "innodb_log_write_ahead_size cannot"
23346 " be set higher than innodb_page_size.");
23347
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
163 } else if (val != in_val) {
23348 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23349 "innodb_log_write_ahead_size should be"
23350 " set to power of 2, in range [%lu,%lu]",
23351 INNODB_LOG_WRITE_AHEAD_SIZE_MIN,
23352 INNODB_LOG_WRITE_AHEAD_SIZE_MAX);
23353 }
23354
23355
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
163 if (val != in_val) {
23356 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23357 "Setting innodb_log_write_ahead_size"
23358 " to %lu",
23359 val);
23360 }
23361
23362 163 log_write_ahead_resize(*log_sys, val);
23363 163 }
23364
23365 /** Update the system variable innodb_log_buffer_size using the "saved"
23366 value. This function is registered as a callback with MySQL.
23367 @param[in] save immediate result from check function */
23368 165 static void innodb_log_buffer_size_update(THD *, SYS_VAR *, void *,
23369 const void *save) {
23370 165 const ulong val = *static_cast<const ulong *>(save);
23371
23372
3/6
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 5 not taken.
165 ib::info(ER_IB_MSG_1255) << "Setting innodb_log_buffer_size to " << val;
23373
23374
2/4
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 165 times.
165 if (!log_buffer_resize(*log_sys, val)) {
23375 /* This could happen if we tried to decrease size of the
23376 log buffer but we had more data in the log buffer than
23377 the new size. We could have asked for writing the data to
23378 disk, after x-locking the log buffer, but this could lead
23379 to deadlock if there was no space in log files and checkpoint
23380 was required (because checkpoint writes new redo records
23381 when persisting dd table buffer). That's why we don't ask
23382 for writing to disk. */
23383
23384 ib::error(ER_IB_MSG_1256) << "Failed to change size of the log buffer."
23385 " Try flushing the log buffer first.";
23386 }
23387 165 }
23388
23389 /** Update the innodb_log_writer_threads parameter.
23390 @param[out] var_ptr current value
23391 @param[in] save immediate result from check function */
23392 6 static void innodb_log_writer_threads_update(THD *, SYS_VAR *, void *var_ptr,
23393 const void *save) {
23394 6 *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save);
23395
23396 /* pause/resume the log writer threads based on innodb_log_writer_threads
23397 value. */
23398 6 log_control_writer_threads(*log_sys);
23399 6 }
23400
23401 /** Update the system variable innodb_redo_log_capacity using the "saved"
23402 value. This function is registered as a callback with MySQL.
23403 @param[in] thd thread handle
23404 @param[in] save immediate result from check function */
23405 10 static void innodb_redo_log_capacity_update(THD *thd, SYS_VAR *, void *,
23406 const void *save) {
23407 10 const auto new_value = *static_cast<const ulonglong *>(save);
23408
23409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 ut_a(LOG_CAPACITY_MIN <= new_value);
23410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 ut_a(new_value <= LOG_CAPACITY_MAX);
23411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 ut_a(new_value % MB == 0);
23412
23413 10 srv_redo_log_capacity = new_value;
23414
23415
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 if (new_value == srv_redo_log_capacity_used) {
23416 4 return;
23417 }
23418
23419 6 srv_redo_log_capacity_used = new_value;
23420
23421 6 ib::info(ER_IB_MSG_LOG_FILES_CAPACITY_CHANGED,
23422
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 srv_redo_log_capacity_used / MB);
23423
23424 6 log_files_resize_requested(*log_sys);
23425
23426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!log_sys->concurrency_margin_is_safe.load()) {
23427 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23428 "Current innodb_redo_log_capacity"
23429 " is too small for safety of redo log files."
23430 " Consider increasing it or decreasing"
23431 " innodb_thread_concurrency.");
23432 }
23433 }
23434
23435 /** Update the system variable innodb_thread_concurrency using the "saved"
23436 value. This function is registered as a callback with MySQL.
23437 @param[in] thd thread handle
23438 @param[in] save immediate result from check function */
23439 36 static void innodb_thread_concurrency_update(THD *thd, SYS_VAR *, void *,
23440 const void *save) {
23441 36 srv_thread_concurrency = *static_cast<const ulong *>(save);
23442
23443 36 ib::info(ER_IB_MSG_THREAD_CONCURRENCY_CHANGED, srv_thread_concurrency);
23444
23445 36 log_files_thread_concurrency_updated(*log_sys);
23446
23447
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 33 times.
36 if (!log_sys->concurrency_margin_is_safe.load()) {
23448 3 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23449 "Current innodb_thread_concurrency"
23450 " is too big for safety of redo log files."
23451 " Consider decreasing it or increasing"
23452 " innodb_redo_log_capacity.");
23453 }
23454 36 }
23455
23456 /** Empty free list algorithm. This function is registered as a callback with
23457 MySQL.
23458 @param[in] thd thread handle
23459 @param[in] var pointer to system variable
23460 @param[out] save immediate result for update function
23461 @param[in] value incoming string
23462 @return 0 for valid algorithm */
23463 13 static int innodb_srv_empty_free_list_algorithm_validate(
23464 THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) {
23465 char buff[STRING_BUFFER_USUAL_SIZE];
23466 13 int len = sizeof(buff);
23467
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 const char *const algorithm_name = value->val_str(value, buff, &len);
23468
23469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!algorithm_name) return (1);
23470
23471 ulint algo;
23472 22 for (algo = 0;
23473
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
22 algo < array_elements(innodb_empty_free_list_algorithm_names) - 1;
23474 algo++) {
23475
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9 times.
20 if (!innobase_strcasecmp(algorithm_name,
23476 innodb_empty_free_list_algorithm_names[algo]))
23477 11 break;
23478 }
23479
23480
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (algo == array_elements(innodb_empty_free_list_algorithm_names) - 1)
23481 2 return (1);
23482
23483 11 const auto algorithm = static_cast<srv_empty_free_list_t>(algo);
23484
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 if (!innodb_empty_free_list_algorithm_allowed(algorithm)) {
23485
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 sql_print_warning(
23486 "InnoDB: innodb_empty_free_list_algorithm = 'backoff' "
23487 "requires at least 20MB buffer pool instances.\n");
23488 2 return (1);
23489 }
23490
23491 9 *reinterpret_cast<ulong *>(save) = static_cast<ulong>(algorithm);
23492 9 return (0);
23493 }
23494
23495 10 static int innodb_encryption_threads_validate(
23496 /*=================================*/
23497 THD *thd, /*!< in: thread handle */
23498 SYS_VAR *var, /*!< in: pointer to system
23499 variable */
23500 void *save, /*!< out: immediate result
23501 for update function */
23502 struct st_mysql_value *value) /*!< in: incoming string */
23503 {
23504 long long intbuf;
23505
23506
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 DBUG_TRACE;
23507
23508
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (value->val_int(value, &intbuf)) {
23509 /* The value is NULL. That is invalid. */
23510 return 1;
23511 }
23512
23513 10 bool is_val_fixed = false;
23514 10 long long requested_threads = intbuf;
23515
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (intbuf < 0) {
23516 2 requested_threads = 0;
23517 2 is_val_fixed = true;
23518
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 } else if (intbuf > MAX_ENCRYPTION_THREADS) {
23519 2 requested_threads = MAX_ENCRYPTION_THREADS;
23520 2 is_val_fixed = true;
23521 }
23522
23523
3/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
10 if (throw_bounds_warning(thd, "innodb_encryption_threads", is_val_fixed,
23524 intbuf)) {
23525 2 return 1;
23526 }
23527
23528
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
8 if (srv_n_fil_crypt_threads_requested == 0 && requested_threads > 0) {
23529 // We are starting encryption threads, we must lock
23530 // the keyring plugins
23531
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 uint number_of_keyrings_locked = lock_keyrings(NULL);
23532
23533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (number_of_keyrings_locked == 0) {
23534 my_printf_error(ER_WRONG_ARGUMENTS,
23535 "InnoDB: cannot enable encryption threads, "
23536 "keyring plugin is not available",
23537 MYF(0));
23538 return 1;
23539 }
23540
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (Encryption::is_keyring_alive() == false) {
23541 my_printf_error(
23542 ER_WRONG_ARGUMENTS,
23543 "InnoDB: keyring plugin is installed but it seems it was not "
23544 "properly initialized. Cannot enable encryption threads.",
23545 MYF(0));
23546 unlock_keyrings(NULL);
23547 return 1;
23548 }
23549
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
8 } else if (requested_threads == 0 && srv_n_fil_crypt_threads_requested > 0) {
23550 // We are disabling encryption
23551 // threads, unlock the keyrings
23552
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 unlock_keyrings(NULL);
23553 }
23554
23555 8 *reinterpret_cast<ulong *>(save) = static_cast<ulong>(requested_threads);
23556
23557 8 return 0;
23558 10 }
23559
23560 /******************************************************************
23561 Update the system variable innodb_encryption_threads */
23562 8 static void innodb_encryption_threads_update(
23563 /*=============================*/
23564 THD *thd, /*!< in: thread handle */
23565 SYS_VAR *var, /*!< in: pointer to
23566 system variable */
23567 void *var_ptr, /*!< out: where the
23568 formal string goes */
23569 const void *save) /*!< in: immediate result
23570 from check function */
23571 {
23572 8 mysql_mutex_unlock(&LOCK_global_system_variables);
23573 8 fil_crypt_set_thread_cnt(*static_cast<const uint *>(save));
23574 8 mysql_mutex_lock(&LOCK_global_system_variables);
23575 8 }
23576
23577 /******************************************************************
23578 Update the system variable innodb_encryption_rotate_key_age */
23579 3 static void innodb_encryption_rotate_key_age_update(
23580 /*====================================*/
23581 THD *thd, /*!< in: thread handle */
23582 SYS_VAR *var, /*!< in: pointer to
23583 system variable */
23584 void *var_ptr, /*!< out: where the
23585 formal string goes */
23586 const void *save) /*!< in: immediate result
23587 from check function */
23588 {
23589 3 fil_crypt_set_rotate_key_age(*static_cast<const uint *>(save));
23590 3 }
23591
23592 /******************************************************************
23593 Update the system variable innodb_encryption_rotation_iops */
23594 3 static void innodb_encryption_rotation_iops_update(
23595 /*===================================*/
23596 THD *thd, /*!< in: thread handle */
23597 SYS_VAR *var, /*!< in: pointer to
23598 system variable */
23599 void *var_ptr, /*!< out: where the
23600 formal string goes */
23601 const void *save) /*!< in: immediate result
23602 from check function */
23603 {
23604 3 fil_crypt_set_rotation_iops(*static_cast<const uint *>(save));
23605 3 }
23606
23607 /** Update the innodb_log_checksums parameter.
23608 @param[out] var_ptr current value
23609 @param[in] save immediate result from check function */
23610 7 static void innodb_log_checksums_update(THD *, SYS_VAR *, void *var_ptr,
23611 const void *save) {
23612 7 bool check = *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save);
23613
23614 /* Make sure we are the only log user */
23615 7 innodb_log_checksums_func_update(check);
23616 7 }
23617
23618 /** Enable or disable encryption of temporary tablespace
23619 @param[in] thd thread handle
23620 @param[in] var system variable
23621 @param[out] var_ptr current value
23622 @param[in] save immediate result from check function */
23623 69 static void innodb_temp_tablespace_encryption_update(THD *thd, SYS_VAR *var,
23624 void *var_ptr,
23625 const void *save) {
23626
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 68 times.
69 if (srv_read_only_mode) {
23627 1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23628 " Temporary tablespace cannot be"
23629 " encrypted in innodb_read_only mode");
23630 1 return;
23631 }
23632
23633 68 bool check = *static_cast<const bool *>(save);
23634
23635 68 dberr_t err = srv_temp_encryption_update(check);
23636
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
68 if (err != DB_SUCCESS) {
23637 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
23638 " Temporary tablespace couldn't be"
23639 " encrypted. Check if keyring plugin"
23640 " is loaded.");
23641 } else {
23642 66 *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save);
23643 }
23644 }
23645
23646 static SHOW_VAR innodb_status_variables_export[] = {
23647 {"Innodb", (char *)&show_innodb_vars, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
23648 {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}};
23649
23650 static struct st_mysql_storage_engine innobase_storage_engine = {
23651 MYSQL_HANDLERTON_INTERFACE_VERSION};
23652
23653 /* plugin options */
23654
23655 static MYSQL_SYSVAR_ENUM(
23656 checksum_algorithm, srv_checksum_algorithm, PLUGIN_VAR_RQCMDARG,
23657 "The algorithm InnoDB uses for page checksumming. Possible values are"
23658 " CRC32 (hardware accelerated if the CPU supports it)"
23659 " write crc32, allow any of the other checksums to match when reading;"
23660 " STRICT_CRC32"
23661 " write crc32, do not allow other algorithms to match when reading;"
23662 " INNODB"
23663 " write a software calculated checksum, allow any other checksums"
23664 " to match when reading;"
23665 " STRICT_INNODB"
23666 " write a software calculated checksum, do not allow other algorithms"
23667 " to match when reading;"
23668 " NONE"
23669 " write a constant magic number, do not do any checksum verification"
23670 " when reading;"
23671 " STRICT_NONE"
23672 " write a constant magic number, do not allow values other than that"
23673 " magic number when reading;"
23674 " Files updated when this option is set to crc32 or strict_crc32 will"
23675 " not be readable by MySQL versions older than 5.6.3",
23676 nullptr, nullptr, SRV_CHECKSUM_ALGORITHM_CRC32,
23677 &innodb_checksum_algorithm_typelib);
23678
23679 static MYSQL_SYSVAR_BOOL(
23680 log_checksums, srv_log_checksums, PLUGIN_VAR_RQCMDARG,
23681 "Whether to compute and require checksums for InnoDB redo log blocks",
23682 nullptr, innodb_log_checksums_update, true);
23683
23684 static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir,
23685 PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
23686 "The common part for InnoDB table spaces.", nullptr,
23687 nullptr, nullptr);
23688
23689 static MYSQL_SYSVAR_BOOL(
23690 stats_include_delete_marked, srv_stats_include_delete_marked,
23691 PLUGIN_VAR_OPCMDARG,
23692 "Include delete marked records when calculating persistent statistics",
23693 nullptr, nullptr, false);
23694
23695 static MYSQL_SYSVAR_ULONG(
23696 io_capacity, srv_io_capacity, PLUGIN_VAR_RQCMDARG,
23697 "Number of IOPs the server can do. Tunes the background IO rate", nullptr,
23698 innodb_io_capacity_update, 200, 100, ~0UL, 0);
23699
23700 static MYSQL_SYSVAR_ULONG(io_capacity_max, srv_max_io_capacity,
23701 PLUGIN_VAR_RQCMDARG,
23702 "Limit to which innodb_io_capacity can be inflated.",
23703 nullptr, innodb_io_capacity_max_update,
23704 SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT, 100,
23705 SRV_MAX_IO_CAPACITY_LIMIT, 0);
23706
23707 #ifdef UNIV_DEBUG
23708 static MYSQL_SYSVAR_BOOL(background_drop_list_empty,
23709 innodb_background_drop_list_empty, PLUGIN_VAR_OPCMDARG,
23710 "Wait for the background drop list to become empty",
23711 nullptr, wait_background_drop_list_empty, false);
23712
23713 static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now,
23714 PLUGIN_VAR_OPCMDARG, "Set purge state to RUN", nullptr,
23715 purge_run_now_set, false);
23716
23717 static MYSQL_SYSVAR_BOOL(purge_stop_now, innodb_purge_stop_now,
23718 PLUGIN_VAR_OPCMDARG, "Set purge state to STOP",
23719 nullptr, purge_stop_now_set, false);
23720
23721 static MYSQL_SYSVAR_BOOL(log_flush_now, innodb_log_flush_now,
23722 PLUGIN_VAR_OPCMDARG,
23723 "Force flush of redo up to current lsn", nullptr,
23724 log_flush_now_set, false);
23725
23726 static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now,
23727 PLUGIN_VAR_OPCMDARG, "Force sharp checkpoint now",
23728 nullptr, checkpoint_now_set, false);
23729
23730 static MYSQL_SYSVAR_BOOL(log_checkpoint_fuzzy_now,
23731 innodb_log_checkpoint_fuzzy_now, PLUGIN_VAR_OPCMDARG,
23732 "Force fuzzy checkpoint now", nullptr,
23733 checkpoint_fuzzy_now_set, false);
23734
23735 static MYSQL_SYSVAR_BOOL(checkpoint_disabled, srv_checkpoint_disabled,
23736 PLUGIN_VAR_OPCMDARG, "Disable checkpoints", nullptr,
23737 checkpoint_disabled_update, false);
23738
23739 static MYSQL_SYSVAR_BOOL(buf_flush_list_now, innodb_buf_flush_list_now,
23740 PLUGIN_VAR_OPCMDARG, "Force dirty page flush now",
23741 nullptr, buf_flush_list_now_set, false);
23742
23743 static MYSQL_SYSVAR_UINT(
23744 merge_threshold_set_all_debug, innodb_merge_threshold_set_all_debug,
23745 PLUGIN_VAR_RQCMDARG,
23746 "Override current MERGE_THRESHOLD setting for all indexes at dictionary"
23747 " cache by the specified value dynamically, at the time.",
23748 nullptr, innodb_merge_threshold_set_all_debug_update,
23749 DICT_INDEX_MERGE_THRESHOLD_DEFAULT, 1, 50, 0);
23750
23751 extern ulong srv_fatal_semaphore_wait_threshold;
23752 static MYSQL_SYSVAR_ULONG(
23753 semaphore_wait_timeout_debug, srv_fatal_semaphore_wait_threshold,
23754 PLUGIN_VAR_RQCMDARG,
23755 "Number of seconds that a semaphore can be held. If semaphore wait crosses"
23756 "this value, server will crash",
23757 nullptr, nullptr, 600, 25, 600, 0);
23758 #endif /* UNIV_DEBUG */
23759
23760 static MYSQL_SYSVAR_ULONG(
23761 purge_batch_size, srv_purge_batch_size, PLUGIN_VAR_OPCMDARG,
23762 "Number of UNDO log pages to purge in one batch from the history list.",
23763 nullptr, nullptr, 300, /* Default setting */
23764 1, /* Minimum value */
23765 5000, 0); /* Maximum value */
23766
23767 static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads,
23768 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
23769 "Purge threads can be from 1 to 32. Default is 4.",
23770 nullptr, nullptr, 4, /* Default setting */
23771 1, /* Minimum value */
23772 MAX_PURGE_THREADS, 0); /* Maximum value */
23773
23774 static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size,
23775 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
23776 "Size of the mutex/lock wait array.", nullptr,
23777 nullptr, 1, /* Default setting */
23778 1, /* Minimum value */
23779 1024, 0); /* Maximum value */
23780
23781 static MYSQL_SYSVAR_ULONG(
23782 fast_shutdown, srv_fast_shutdown, PLUGIN_VAR_OPCMDARG,
23783 "Speeds up the shutdown process of the InnoDB storage engine. Possible"
23784 " values are 0, 1 (faster) or 2 (fastest - crash-like).",
23785 nullptr, nullptr, 1, 0, 2, 0);
23786
23787 static MYSQL_SYSVAR_BOOL(
23788 file_per_table, srv_file_per_table, PLUGIN_VAR_NOCMDARG,
23789 "Stores each InnoDB table to an .ibd file in the database dir.", nullptr,
23790 nullptr, true);
23791
23792 static MYSQL_SYSVAR_STR(ft_server_stopword_table,
23793 innobase_server_stopword_table,
23794 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
23795 "The user supplied stopword table name.",
23796 innodb_stopword_table_validate, nullptr, nullptr);
23797
23798 extern uint srv_flush_log_at_timeout;
23799 static MYSQL_SYSVAR_UINT(flush_log_at_timeout, srv_flush_log_at_timeout,
23800 PLUGIN_VAR_OPCMDARG,
23801 "Write and flush logs every (n) second.", nullptr,
23802 nullptr, 1, 0, 2700, 0);
23803
23804 static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
23805 PLUGIN_VAR_OPCMDARG,
23806 "Set to 0 (write and flush once per second),"
23807 " 1 (write and flush at each commit),"
23808 " or 2 (write at commit, flush once per second).",
23809 nullptr, nullptr, 1, 0, 2, 0);
23810
23811 static MYSQL_SYSVAR_ENUM(flush_method, innodb_flush_method,
23812 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
23813 "With which method to flush data", nullptr, nullptr, 0,
23814 &innodb_flush_method_typelib);
23815
23816 static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted,
23817 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY |
23818 PLUGIN_VAR_NOPERSIST,
23819 "Force InnoDB to load metadata of corrupted table.",
23820 nullptr, nullptr, false);
23821
23822 static MYSQL_SYSVAR_ULONG(show_locks_held, srv_show_locks_held,
23823 PLUGIN_VAR_RQCMDARG,
23824 "Number of locks held to print for each InnoDB "
23825 "transaction in SHOW INNODB STATUS.",
23826 NULL, NULL, 10, 0, 1000, 0);
23827
23828 static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir,
23829 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
23830 PLUGIN_VAR_NOPERSIST,
23831 "Path to InnoDB log files.", nullptr, nullptr, nullptr);
23832
23833 static MYSQL_SYSVAR_ULONG(
23834 page_cleaners, srv_n_page_cleaners,
23835 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
23836 "Page cleaner threads can be from 1 to 64. Default is 4.", nullptr, nullptr,
23837 4, 1, 64, 0);
23838
23839 static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
23840 PLUGIN_VAR_RQCMDARG,
23841 "Percentage of dirty pages allowed in bufferpool.",
23842 nullptr, innodb_max_dirty_pages_pct_update, 90.0, 0,
23843 99.999, 0);
23844
23845 static MYSQL_SYSVAR_DOUBLE(
23846 max_dirty_pages_pct_lwm, srv_max_dirty_pages_pct_lwm, PLUGIN_VAR_RQCMDARG,
23847 "Percentage of dirty pages at which flushing kicks in.", nullptr,
23848 innodb_max_dirty_pages_pct_lwm_update, 10, 0, 99.999, 0);
23849
23850 static MYSQL_SYSVAR_ULONG(
23851 adaptive_flushing_lwm, srv_adaptive_flushing_lwm, PLUGIN_VAR_RQCMDARG,
23852 "Percentage of log capacity below which no adaptive flushing happens.",
23853 nullptr, nullptr, 10, 0, 70, 0);
23854
23855 static MYSQL_SYSVAR_BOOL(
23856 adaptive_flushing, srv_adaptive_flushing, PLUGIN_VAR_NOCMDARG,
23857 "Attempt flushing dirty pages to avoid IO bursts at checkpoints.", nullptr,
23858 nullptr, true);
23859
23860 static MYSQL_SYSVAR_BOOL(
23861 flush_sync, srv_flush_sync, PLUGIN_VAR_NOCMDARG,
23862 "Allow IO bursts at the checkpoints ignoring io_capacity setting.", nullptr,
23863 nullptr, true);
23864
23865 static MYSQL_SYSVAR_ULONG(
23866 flushing_avg_loops, srv_flushing_avg_loops, PLUGIN_VAR_RQCMDARG,
23867 "Number of iterations over which the background flushing is averaged.",
23868 nullptr, nullptr, 30, 1, 1000, 0);
23869
23870 static MYSQL_SYSVAR_ULONG(
23871 max_purge_lag, srv_max_purge_lag, PLUGIN_VAR_RQCMDARG,
23872 "Desired maximum length of the purge queue (0 = no limit)", nullptr,
23873 nullptr, 0, 0, ~0UL, 0);
23874
23875 static MYSQL_SYSVAR_ULONG(max_purge_lag_delay, srv_max_purge_lag_delay,
23876 PLUGIN_VAR_RQCMDARG,
23877 "Maximum delay of user threads in micro-seconds",
23878 nullptr, nullptr, 0L, /* Default seting */
23879 0L, /* Minimum value */
23880 10000000UL, 0); /* Maximum value */
23881
23882 static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
23883 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
23884 "Roll back the complete transaction on lock wait "
23885 "timeout, for 4.x compatibility (disabled by default)",
23886 nullptr, nullptr, false);
23887
23888 static MYSQL_SYSVAR_BOOL(
23889 status_file, innobase_create_status_file,
23890 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR,
23891 "Enable SHOW ENGINE INNODB STATUS output in the innodb_status.<pid> file",
23892 nullptr, nullptr, false);
23893
23894 static MYSQL_SYSVAR_BOOL(
23895 stats_on_metadata, innobase_stats_on_metadata, PLUGIN_VAR_OPCMDARG,
23896 "Enable statistics gathering for metadata commands such as"
23897 " SHOW TABLE STATUS for tables that use transient statistics (off by "
23898 "default)",
23899 nullptr, nullptr, false);
23900
23901 static MYSQL_SYSVAR_ULONGLONG(
23902 stats_transient_sample_pages, srv_stats_transient_sample_pages,
23903 PLUGIN_VAR_RQCMDARG,
23904 "The number of leaf index pages to sample when calculating transient"
23905 " statistics (if persistent statistics are not used, default 8)",
23906 nullptr, nullptr, 8, 1, ~0ULL, 0);
23907
23908 static MYSQL_SYSVAR_BOOL(
23909 stats_persistent, srv_stats_persistent, PLUGIN_VAR_OPCMDARG,
23910 "InnoDB persistent statistics enabled for all tables unless overridden"
23911 " at table level",
23912 nullptr, nullptr, true);
23913
23914 static MYSQL_SYSVAR_BOOL(
23915 stats_auto_recalc, srv_stats_auto_recalc, PLUGIN_VAR_OPCMDARG,
23916 "InnoDB automatic recalculation of persistent statistics enabled for all"
23917 " tables unless overridden at table level (automatic recalculation is only"
23918 " done when InnoDB decides that the table has changed too much and needs a"
23919 " new statistics)",
23920 nullptr, nullptr, true);
23921
23922 static MYSQL_SYSVAR_ULONGLONG(
23923 stats_persistent_sample_pages, srv_stats_persistent_sample_pages,
23924 PLUGIN_VAR_RQCMDARG,
23925 "The number of leaf index pages to sample when calculating persistent"
23926 " statistics (by ANALYZE, default 20)",
23927 nullptr, nullptr, 20, 1, ~0ULL, 0);
23928
23929 static MYSQL_SYSVAR_BOOL(
23930 adaptive_hash_index, btr_search_enabled, PLUGIN_VAR_OPCMDARG,
23931 "Enable InnoDB adaptive hash index (enabled by default). "
23932 " Disable with --skip-innodb-adaptive-hash-index.",
23933 nullptr, innodb_adaptive_hash_index_update, true);
23934
23935 /** Number of distinct partitions of AHI.
23936 Each partition is protected by its own latch and so we have parts number
23937 of latches protecting complete search system. */
23938 static MYSQL_SYSVAR_ULONG(
23939 adaptive_hash_index_parts, btr_ahi_parts,
23940 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
23941 "Number of InnoDB Adaptive Hash Index Partitions. (default = 8). ", nullptr,
23942 nullptr, 8, 1, 512, 0);
23943
23944 extern ulong srv_replication_delay;
23945 static MYSQL_SYSVAR_ULONG(
23946 replication_delay, srv_replication_delay, PLUGIN_VAR_RQCMDARG,
23947 "Replication thread delay (ms) on the slave server if"
23948 " innodb_thread_concurrency is reached (0 by default)",
23949 nullptr, nullptr, 0, 0, ~0UL, 0);
23950
23951 static MYSQL_SYSVAR_UINT(
23952 compression_level, page_zip_level, PLUGIN_VAR_RQCMDARG,
23953 "Compression level used for compressed row format. 0 is no compression"
23954 ", 1 is fastest, 9 is best compression and default is 6.",
23955 nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0);
23956
23957 static MYSQL_SYSVAR_BOOL(
23958 log_compressed_pages, page_zip_log_pages, PLUGIN_VAR_OPCMDARG,
23959 "Enables/disables the logging of entire compressed page images."
23960 " InnoDB logs the compressed pages to prevent corruption if"
23961 " the zlib compression algorithm changes."
23962 " When turned OFF, InnoDB will assume that the zlib"
23963 " compression algorithm doesn't change.",
23964 nullptr, nullptr, true);
23965
23966 static MYSQL_SYSVAR_ULONG(autoextend_increment,
23967 sys_tablespace_auto_extend_increment,
23968 PLUGIN_VAR_RQCMDARG,
23969 "Data file autoextend increment in megabytes",
23970 nullptr, nullptr, 64L, 1L, 1000L, 0);
23971
23972 static MYSQL_SYSVAR_BOOL(
23973 dedicated_server, srv_dedicated_server,
23974 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST | PLUGIN_VAR_READONLY,
23975 "Automatically scale innodb_buffer_pool_size and innodb_redo_log_capacity "
23976 "based on system memory. Also set innodb_flush_method=O_DIRECT_NO_FSYNC, "
23977 "if supported",
23978 nullptr, nullptr, false);
23979
23980 static MYSQL_SYSVAR_DOUBLE(
23981 segment_reserve_factor, fseg_reserve_pct, PLUGIN_VAR_OPCMDARG,
23982 "The segment_reserve_factor is the ratio x/y expressed in percentage,"
23983 " where x is the number of free pages in the segment, and y is the total"
23984 " number of pages in the segment. The number of used pages in the segment"
23985 " is given by (y-x). The number of free pages in the segment (x) will be"
23986 " maintained such that the actual segment_reserve_factor will be >= the"
23987 " requested segment_reserve_factor, which is contained in this variable.",
23988 nullptr, nullptr, FSEG_RESERVE_PCT_DFLT, FSEG_RESERVE_PCT_MIN,
23989 FSEG_RESERVE_PCT_MAX, 0);
23990
23991 /* If the default value of innodb_buffer_pool_size is increased to be more than
23992 BUF_POOL_SIZE_THRESHOLD (srv/srv0start.cc), then srv_buf_pool_instances_default
23993 can be removed and 8 used instead. The problem with the current setup is that
23994 with 128MiB default buffer pool size and 8 instances by default we would emit
23995 a warning when no options are specified. */
23996 static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, srv_buf_pool_curr_size,
23997 PLUGIN_VAR_RQCMDARG |
23998 PLUGIN_VAR_PERSIST_AS_READ_ONLY,
23999 "The size of the memory buffer InnoDB uses to "
24000 "cache data and indexes of its tables.",
24001 nullptr, innodb_buffer_pool_size_update,
24002 static_cast<longlong>(srv_buf_pool_def_size),
24003 static_cast<longlong>(srv_buf_pool_min_size),
24004 longlong{srv_buf_pool_max_size}, 1024 * 1024L);
24005
24006 static MYSQL_SYSVAR_ULONGLONG(
24007 buffer_pool_chunk_size, srv_buf_pool_chunk_unit,
24008 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24009 "Size of a single memory chunk within each buffer pool instance"
24010 " for resizing buffer pool. Online buffer pool resizing happens"
24011 " at this granularity.",
24012 nullptr, nullptr, 128 * 1024 * 1024, ulonglong{srv_buf_pool_chunk_unit_min},
24013 ulonglong{srv_buf_pool_chunk_unit_max},
24014 ulonglong{srv_buf_pool_chunk_unit_blk_sz});
24015
24016 #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
24017 static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks,
24018 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
24019 "Number of rw_locks protecting buffer pool "
24020 "page_hash. Rounded up to the next power of 2",
24021 nullptr, nullptr, 16, 1, MAX_PAGE_HASH_LOCKS, 0);
24022
24023 #ifdef UNIV_LINUX
24024
24025 static MYSQL_SYSVAR_ULONG(sched_priority_purge, srv_sched_priority_purge,
24026 PLUGIN_VAR_RQCMDARG,
24027 "Nice value for the purge thread scheduling", NULL,
24028 innodb_sched_priority_purge_update, 19, 0, 39, 0);
24029
24030 static MYSQL_SYSVAR_ULONG(sched_priority_io, srv_sched_priority_io,
24031 PLUGIN_VAR_RQCMDARG,
24032 "Nice value for the I/O handler thread scheduling",
24033 NULL, innodb_sched_priority_io_update, 19, 0, 39, 0);
24034
24035 static MYSQL_SYSVAR_ULONG(sched_priority_master, srv_sched_priority_master,
24036 PLUGIN_VAR_RQCMDARG,
24037 "Nice value for the master thread scheduling", NULL,
24038 innodb_sched_priority_master_update, 19, 0, 39, 0);
24039
24040 static MYSQL_SYSVAR_BOOL(
24041 priority_purge, srv_purge_thread_priority, PLUGIN_VAR_OPCMDARG,
24042 "Make purge coordinator and worker threads acquire shared resources with "
24043 "priority",
24044 NULL, NULL, false);
24045
24046 static MYSQL_SYSVAR_BOOL(
24047 priority_master, srv_master_thread_priority, PLUGIN_VAR_OPCMDARG,
24048 "Make buffer pool cleaner thread acquire shared resources with priority",
24049 NULL, NULL, false);
24050
24051 #endif /* UNIV_LINUX */
24052
24053 // TODO: the option is here, but currently a no-op
24054 static MYSQL_SYSVAR_ULONG(
24055 cleaner_max_lru_time, srv_cleaner_max_lru_time, PLUGIN_VAR_RQCMDARG,
24056 "The maximum time limit for a single LRU tail flush iteration by the page "
24057 "cleaner thread in miliseconds",
24058 NULL, NULL, 1000, 0, ~0UL, 0);
24059
24060 // TODO: the option is here, but currently a no-op
24061 static MYSQL_SYSVAR_ULONG(cleaner_max_flush_time, srv_cleaner_max_flush_time,
24062 PLUGIN_VAR_RQCMDARG,
24063 "The maximum time limit for a single flush list "
24064 "flush iteration by the page "
24065 "cleaner thread in miliseconds",
24066 NULL, NULL, 1000, 0, ~0UL, 0);
24067 #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
24068
24069 static MYSQL_SYSVAR_BOOL(
24070 validate_tablespace_paths, srv_validate_tablespace_paths,
24071 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
24072 "Enable validation of tablespace paths against the DD. (enabled by "
24073 "default)."
24074 " Disable with --skip-innodb-validate-tablespace-paths.",
24075 nullptr, nullptr, true);
24076
24077 static MYSQL_SYSVAR_BOOL(use_fdatasync, srv_use_fdatasync, PLUGIN_VAR_NOCMDARG,
24078 "Use fdatasync() instead of the default fsync().",
24079 nullptr, nullptr, false);
24080
24081 // clang-format off
24082 static MYSQL_SYSVAR_ENUM(
24083 doublewrite, dblwr::g_mode, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
24084 "Enable InnoDB doublewrite buffer (enabled by default)."
24085 " Disable with --skip-innodb-doublewrite.",
24086 nullptr, doublewrite_update, dblwr::Mode::ON, &innodb_doublewrite_typelib);
24087
24088 static MYSQL_SYSVAR_BOOL(
24089 extend_and_initialize, tbsp_extend_and_initialize, PLUGIN_VAR_NOCMDARG,
24090 "Initialize the allocated space by writing zeros (enabled by default).",
24091 nullptr, innodb_extend_and_initialize_update, true);
24092
24093 static MYSQL_SYSVAR_STR(
24094 doublewrite_dir, innobase_doublewrite_dir, PLUGIN_VAR_READONLY,
24095 "Use a separate directory for the doublewrite buffer files, ", nullptr, nullptr,
24096 nullptr);
24097
24098 static MYSQL_SYSVAR_ULONG(
24099 doublewrite_pages, dblwr::n_pages,
24100 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24101 "Number of double write pages per thread" , nullptr, nullptr, 0, 0, 512, 0);
24102
24103 static MYSQL_SYSVAR_ULONG(
24104 doublewrite_files, dblwr::n_files,
24105 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24106 "Number of double write files", nullptr, nullptr, 0, 0, 256, 0);
24107
24108 static MYSQL_SYSVAR_ULONG(
24109 doublewrite_batch_size, dblwr::batch_size,
24110 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24111 "Number of double write pages to write in a batch", nullptr, nullptr,
24112 0, 0, 256, 0);
24113 // clang-format on
24114
24115 static MYSQL_SYSVAR_ENUM(
24116 cleaner_lsn_age_factor, srv_cleaner_lsn_age_factor, PLUGIN_VAR_OPCMDARG,
24117 "The formula for LSN age factor for page cleaner adaptive flushing. "
24118 "LEGACY: Original Oracle MySQL formula. "
24119 "HIGH_CHECKPOINT: (the default) Percona Server formula.",
24120 nullptr, nullptr, SRV_CLEANER_LSN_AGE_FACTOR_HIGH_CHECKPOINT,
24121 &innodb_cleaner_lsn_age_factor_typelib);
24122
24123 static MYSQL_SYSVAR_ENUM(
24124 empty_free_list_algorithm, srv_empty_free_list_algorithm,
24125 PLUGIN_VAR_OPCMDARG,
24126 "The algorithm to use for empty free list handling. Allowed values: "
24127 "LEGACY: (the default) Original Oracle MySQL handling with single page "
24128 "flushes; "
24129 "BACKOFF: Wait until cleaner produces a free page.",
24130 innodb_srv_empty_free_list_algorithm_validate, nullptr,
24131 SRV_EMPTY_FREE_LIST_LEGACY, &innodb_empty_free_list_algorithm_typelib);
24132
24133 static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances,
24134 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24135 "Number of buffer pool instances, set to higher "
24136 "value on high-end machines to increase scalability",
24137 nullptr, nullptr, srv_buf_pool_instances_default, 0,
24138 MAX_BUFFER_POOLS, 0);
24139
24140 static MYSQL_SYSVAR_STR(
24141 buffer_pool_filename, srv_buf_dump_filename,
24142 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
24143 "Filename to/from which to dump/load the InnoDB buffer pool",
24144 innodb_srv_buf_dump_filename_validate, nullptr,
24145 SRV_BUF_DUMP_FILENAME_DEFAULT);
24146
24147 static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now,
24148 PLUGIN_VAR_RQCMDARG,
24149 "Trigger an immediate dump of the buffer pool into a "
24150 "file named @@innodb_buffer_pool_filename",
24151 nullptr, buffer_pool_dump_now, false);
24152
24153 static MYSQL_SYSVAR_BOOL(
24154 buffer_pool_dump_at_shutdown, srv_buffer_pool_dump_at_shutdown,
24155 PLUGIN_VAR_RQCMDARG,
24156 "Dump the buffer pool into a file named @@innodb_buffer_pool_filename",
24157 nullptr, nullptr, true);
24158
24159 static MYSQL_SYSVAR_BOOL(
24160 buffer_pool_in_core_file, srv_buffer_pool_in_core_file, PLUGIN_VAR_NOCMDARG,
24161 "This option has no effect if @@core_file is OFF. "
24162 "If @@core_file is ON, and this option is OFF, then the core dump file will"
24163 " be generated only if it is possible to exclude buffer pool from it. "
24164 "As soon as it will be determined that such exclusion is impossible a "
24165 "warning will be emitted and @@core_file will be set to OFF to prevent "
24166 "generating a core dump. "
24167 "If this option is enabled (which is the default), then core dumping "
24168 "logic will not be affected. ",
24169 nullptr, innodb_srv_buffer_pool_in_core_file_update, true);
24170
24171 static MYSQL_SYSVAR_ULONG(
24172 buffer_pool_dump_pct, srv_buf_pool_dump_pct, PLUGIN_VAR_RQCMDARG,
24173 "Dump only the hottest N% of each buffer pool, defaults to 25", nullptr,
24174 nullptr, 25, 1, 100, 0);
24175
24176 static MYSQL_SYSVAR_ULONG(
24177 idle_flush_pct, srv_idle_flush_pct, PLUGIN_VAR_RQCMDARG,
24178 "Up to what percentage of dirty pages to be flushed when server is found"
24179 " idle.",
24180 nullptr, nullptr, srv_idle_flush_pct_default, 0, 100, 0);
24181
24182 #ifdef UNIV_DEBUG
24183 static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict,
24184 PLUGIN_VAR_RQCMDARG, "Evict pages from the buffer pool",
24185 nullptr, innodb_buffer_pool_evict_update, "");
24186 #endif /* UNIV_DEBUG */
24187
24188 static MYSQL_SYSVAR_BOOL(buffer_pool_load_now, innodb_buffer_pool_load_now,
24189 PLUGIN_VAR_RQCMDARG,
24190 "Trigger an immediate load of the buffer pool from a "
24191 "file named @@innodb_buffer_pool_filename",
24192 nullptr, buffer_pool_load_now, false);
24193
24194 static MYSQL_SYSVAR_BOOL(buffer_pool_load_abort, innodb_buffer_pool_load_abort,
24195 PLUGIN_VAR_RQCMDARG,
24196 "Abort a currently running load of the buffer pool",
24197 nullptr, buffer_pool_load_abort, false);
24198
24199 /* there is no point in changing this during runtime, thus readonly */
24200 static MYSQL_SYSVAR_BOOL(
24201 buffer_pool_load_at_startup, srv_buffer_pool_load_at_startup,
24202 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
24203 "Load the buffer pool from a file named @@innodb_buffer_pool_filename",
24204 nullptr, nullptr, true);
24205
24206 static MYSQL_SYSVAR_ULONG(lru_scan_depth, srv_LRU_scan_depth,
24207 PLUGIN_VAR_RQCMDARG,
24208 "How deep to scan LRU to keep it clean", nullptr,
24209 nullptr, 1024, 100, ~0UL, 0);
24210
24211 static MYSQL_SYSVAR_ULONG(flush_neighbors, srv_flush_neighbors,
24212 PLUGIN_VAR_OPCMDARG,
24213 "Set to 0 (don't flush neighbors from buffer pool),"
24214 " 1 (flush contiguous neighbors from buffer pool)"
24215 " or 2 (flush neighbors from buffer pool),"
24216 " when flushing a block",
24217 nullptr, nullptr, 0, 0, 2, 0);
24218
24219 static MYSQL_SYSVAR_ULONG(
24220 commit_concurrency, innobase_commit_concurrency, PLUGIN_VAR_RQCMDARG,
24221 "Helps in performance tuning in heavily concurrent environments.",
24222 innobase_commit_concurrency_validate, nullptr, 0, 0, 1000, 0);
24223
24224 static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
24225 PLUGIN_VAR_RQCMDARG,
24226 "Number of times a thread is allowed to enter InnoDB "
24227 "within the same SQL query after it has once got the "
24228 "ticket",
24229 nullptr, nullptr, 5000L, 1L, UINT_MAX, 0);
24230
24231 static MYSQL_SYSVAR_BOOL(
24232 deadlock_detect, innobase_deadlock_detect, PLUGIN_VAR_NOCMDARG,
24233 "Enable/disable InnoDB deadlock detector (default ON)."
24234 " if set to OFF, deadlock detection is skipped,"
24235 " and we rely on innodb_lock_wait_timeout in case of deadlock.",
24236 nullptr, innobase_deadlock_detect_update, true);
24237
24238 static MYSQL_SYSVAR_LONG(fill_factor, ddl::fill_factor, PLUGIN_VAR_RQCMDARG,
24239 "Percentage of B-tree page filled during bulk insert",
24240 nullptr, nullptr, 100, 10, 100, 0);
24241
24242 static MYSQL_SYSVAR_BOOL(
24243 ft_enable_diag_print, fts_enable_diag_print, PLUGIN_VAR_OPCMDARG,
24244 "Whether to enable additional FTS diagnostic printout ", nullptr, nullptr,
24245 false);
24246
24247 static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache,
24248 PLUGIN_VAR_OPCMDARG,
24249 "Whether to disable OS system file cache for sort I/O",
24250 nullptr, nullptr, false);
24251
24252 static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name,
24253 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_MEMALLOC,
24254 "FTS internal auxiliary table to be checked",
24255 innodb_internal_table_validate, nullptr, nullptr);
24256
24257 static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size,
24258 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24259 "InnoDB Fulltext search cache size in bytes", nullptr,
24260 nullptr, 8000000, 1600000, 80000000, 0);
24261
24262 static MYSQL_SYSVAR_ULONG(
24263 ft_total_cache_size, fts_max_total_cache_size,
24264 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24265 "Total memory allocated for InnoDB Fulltext Search cache", nullptr, nullptr,
24266 640000000, 32000000, 1600000000, 0);
24267
24268 static MYSQL_SYSVAR_ULONG(
24269 ft_result_cache_limit, fts_result_cache_limit, PLUGIN_VAR_RQCMDARG,
24270 "InnoDB Fulltext search query result cache limit in bytes", nullptr,
24271 nullptr, 2000000000L, 1000000L, 4294967295UL, 0);
24272
24273 static MYSQL_SYSVAR_ULONG(
24274 ft_min_token_size, fts_min_token_size,
24275 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24276 "InnoDB Fulltext search minimum token size in characters", nullptr, nullptr,
24277 3, 0, 16, 0);
24278
24279 static MYSQL_SYSVAR_ULONG(
24280 ft_max_token_size, fts_max_token_size,
24281 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24282 "InnoDB Fulltext search maximum token size in characters", nullptr, nullptr,
24283 FTS_MAX_WORD_LEN_IN_CHAR, 10, FTS_MAX_WORD_LEN_IN_CHAR, 0);
24284
24285 static MYSQL_SYSVAR_ULONG(ft_num_word_optimize, fts_num_word_optimize,
24286 PLUGIN_VAR_OPCMDARG,
24287 "InnoDB Fulltext search number of words to optimize "
24288 "for each optimize table call ",
24289 nullptr, nullptr, 2000, 1000, 10000, 0);
24290
24291 static MYSQL_SYSVAR_ULONG(ft_sort_pll_degree, ddl::fts_parser_threads,
24292 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24293 "InnoDB Fulltext search parallel sort degree, will "
24294 "round up to nearest power of 2 number",
24295 nullptr, nullptr, 2, 1, 16, 0);
24296
24297 static MYSQL_SYSVAR_ULONG(sort_buffer_size, srv_sort_buf_size,
24298 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24299 "Memory buffer size for index creation", nullptr,
24300 nullptr, 1048576, 65536, 64 << 20, 0);
24301
24302 static MYSQL_SYSVAR_ULONGLONG(
24303 online_alter_log_max_size, srv_online_max_size, PLUGIN_VAR_RQCMDARG,
24304 "Maximum modification log file size for online index creation", nullptr,
24305 nullptr, 128 << 20, 65536, ~0ULL, 0);
24306
24307 static MYSQL_SYSVAR_BOOL(optimize_fulltext_only, innodb_optimize_fulltext_only,
24308 PLUGIN_VAR_NOCMDARG,
24309 "Only optimize the Fulltext index of the table",
24310 nullptr, nullptr, false);
24311
24312 static MYSQL_SYSVAR_ULONG(read_io_threads, srv_n_read_io_threads,
24313 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24314 "Number of background read I/O threads in InnoDB.",
24315 nullptr, nullptr, 4, 1, 64, 0);
24316
24317 static MYSQL_SYSVAR_ULONG(write_io_threads, srv_n_write_io_threads,
24318 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24319 "Number of background write I/O threads in InnoDB.",
24320 nullptr, nullptr, 4, 1, 64, 0);
24321
24322 static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery,
24323 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24324 "Helps to save your data in case the disk image of "
24325 "the database becomes corrupt.",
24326 nullptr, nullptr, 0, 0, 6, 0);
24327
24328 #ifdef UNIV_DEBUG
24329 static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash,
24330 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24331 "Kills the server during crash recovery.", nullptr,
24332 nullptr, 0, 0, 100, 0);
24333 #endif /* UNIV_DEBUG */
24334
24335 static MYSQL_SYSVAR_ULONG(page_size, srv_page_size,
24336 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY |
24337 PLUGIN_VAR_NOPERSIST,
24338 "Page size to use for all InnoDB tablespaces.",
24339 nullptr, nullptr, UNIV_PAGE_SIZE_DEF,
24340 UNIV_PAGE_SIZE_MIN, UNIV_PAGE_SIZE_MAX, 0);
24341
24342 static MYSQL_SYSVAR_ULONG(
24343 log_buffer_size, srv_log_buffer_size, PLUGIN_VAR_RQCMDARG,
24344 "The size of the buffer which InnoDB uses to write log to the log files"
24345 " on disk.",
24346 nullptr, innodb_log_buffer_size_update, INNODB_LOG_BUFFER_SIZE_DEFAULT,
24347 INNODB_LOG_BUFFER_SIZE_MIN, INNODB_LOG_BUFFER_SIZE_MAX, 1024);
24348
24349 static MYSQL_SYSVAR_ULONGLONG(
24350 log_file_size, srv_log_file_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24351 "Size of each log file before upgrading to 8.0.30. Deprecated.", nullptr,
24352 nullptr, 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L);
24353
24354 static MYSQL_SYSVAR_ULONG(
24355 log_files_in_group, srv_log_n_files,
24356 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24357 "Number of log files before upgrading to 8.0.30. Deprecated.", nullptr,
24358 nullptr, 2, 2, 100, 0);
24359
24360 static MYSQL_SYSVAR_ULONGLONG(
24361 redo_log_capacity, srv_redo_log_capacity,
24362 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_PERSIST_AS_READ_ONLY,
24363 "Limitation for total size of redo log files on disk (expressed in bytes).",
24364 nullptr, innodb_redo_log_capacity_update, 100 * 1024 * 1024,
24365 LOG_CAPACITY_MIN, LOG_CAPACITY_MAX, MB);
24366
24367 #ifdef UNIV_DEBUG_DEDICATED
24368 static MYSQL_SYSVAR_ULONG(
24369 debug_sys_mem_size, srv_debug_system_mem_size,
24370 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24371 "System memory size. It's for debuging dedicated server.", NULL, NULL,
24372 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L);
24373 #endif /* UNIV_DEBUG_DEDICATED */
24374
24375 static MYSQL_SYSVAR_ULONG(log_write_ahead_size, srv_log_write_ahead_size,
24376 PLUGIN_VAR_RQCMDARG,
24377 "Log write ahead unit size to avoid read-on-write,"
24378 " it should match the OS cache block IO size.",
24379 nullptr, innodb_log_write_ahead_size_update,
24380 INNODB_LOG_WRITE_AHEAD_SIZE_DEFAULT,
24381 INNODB_LOG_WRITE_AHEAD_SIZE_MIN,
24382 INNODB_LOG_WRITE_AHEAD_SIZE_MAX,
24383 OS_FILE_LOG_BLOCK_SIZE);
24384
24385 static MYSQL_SYSVAR_BOOL(
24386 log_writer_threads, srv_log_writer_threads, PLUGIN_VAR_RQCMDARG,
24387 "Whether the log writer threads should be activated (ON), or write/flush "
24388 "of the redo log should be done by each thread individually (OFF).",
24389 nullptr, innodb_log_writer_threads_update, true);
24390
24391 static MYSQL_SYSVAR_UINT(
24392 log_spin_cpu_abs_lwm, srv_log_spin_cpu_abs_lwm, PLUGIN_VAR_RQCMDARG,
24393 "Minimum value of cpu time for which spin-delay is used."
24394 " Expressed in percentage of single cpu core.",
24395 nullptr, nullptr, INNODB_LOG_SPIN_CPU_ABS_LWM_DEFAULT, 0, UINT_MAX, 0);
24396
24397 static MYSQL_SYSVAR_UINT(
24398 log_spin_cpu_pct_hwm, srv_log_spin_cpu_pct_hwm, PLUGIN_VAR_RQCMDARG,
24399 "Maximum value of cpu time for which spin-delay is used."
24400 " Expressed in percentage of all cpu cores.",
24401 nullptr, nullptr, INNODB_LOG_SPIN_CPU_PCT_HWM_DEFAULT, 0, 100, 0);
24402
24403 static MYSQL_SYSVAR_ULONG(
24404 log_wait_for_flush_spin_hwm, srv_log_wait_for_flush_spin_hwm,
24405 PLUGIN_VAR_RQCMDARG,
24406 "Maximum value of average log flush time for which spin-delay is used."
24407 " When flushing takes longer, user threads no longer spin when waiting for"
24408 "flushed redo. Expressed in microseconds.",
24409 nullptr, nullptr, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_HWM_DEFAULT, 0, ULONG_MAX,
24410 0);
24411
24412 #ifdef ENABLE_EXPERIMENT_SYSVARS
24413
24414 static MYSQL_SYSVAR_ULONG(
24415 log_write_events, srv_log_write_events,
24416 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24417 "Number of events used for notifications about log write.", NULL, NULL,
24418 INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0);
24419
24420 static MYSQL_SYSVAR_ULONG(
24421 log_flush_events, srv_log_flush_events,
24422 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24423 "Number of events used for notifications about log flush.", NULL, NULL,
24424 INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0);
24425
24426 static MYSQL_SYSVAR_ULONG(
24427 log_recent_written_size, srv_log_recent_written_size,
24428 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24429 "Size of a small buffer, which allows concurrent writes to log buffer.",
24430 NULL, NULL, INNODB_LOG_RECENT_WRITTEN_SIZE_DEFAULT,
24431 INNODB_LOG_RECENT_WRITTEN_SIZE_MIN, INNODB_LOG_RECENT_WRITTEN_SIZE_MAX, 0);
24432
24433 static MYSQL_SYSVAR_ULONG(
24434 log_recent_closed_size, srv_log_recent_closed_size,
24435 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24436 "Size of a small buffer, which allows to break requirement for total order"
24437 " of dirty pages, when they are added to flush lists.",
24438 NULL, NULL, INNODB_LOG_RECENT_CLOSED_SIZE_DEFAULT,
24439 INNODB_LOG_RECENT_CLOSED_SIZE_MIN, INNODB_LOG_RECENT_CLOSED_SIZE_MAX, 0);
24440
24441 static MYSQL_SYSVAR_ULONG(
24442 log_wait_for_write_spin_delay, srv_log_wait_for_write_spin_delay,
24443 PLUGIN_VAR_RQCMDARG,
24444 "Number of spin iterations, when spinning and waiting for log buffer"
24445 " written up to given LSN, before we fallback to loop with sleeps."
24446 " This is not used when user thread has to wait for log flushed to disk.",
24447 NULL, NULL, INNODB_LOG_WAIT_FOR_WRITE_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
24448
24449 extern ulong srv_log_wait_for_write_timeout;
24450 static MYSQL_SYSVAR_ULONG(
24451 log_wait_for_write_timeout, srv_log_wait_for_write_timeout,
24452 PLUGIN_VAR_RQCMDARG,
24453 "Timeout used when waiting for redo write (microseconds).", NULL, NULL,
24454 INNODB_LOG_WAIT_FOR_WRITE_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
24455
24456 static MYSQL_SYSVAR_ULONG(
24457 log_wait_for_flush_spin_delay, srv_log_wait_for_flush_spin_delay,
24458 PLUGIN_VAR_RQCMDARG,
24459 "Number of spin iterations, when spinning and waiting for log flushed.",
24460 NULL, NULL, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
24461
24462 extern ulong srv_log_wait_for_flush_timeout;
24463 static MYSQL_SYSVAR_ULONG(
24464 log_wait_for_flush_timeout, srv_log_wait_for_flush_timeout,
24465 PLUGIN_VAR_RQCMDARG,
24466 "Timeout used when waiting for redo flush (microseconds).", NULL, NULL,
24467 INNODB_LOG_WAIT_FOR_FLUSH_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
24468
24469 static MYSQL_SYSVAR_ULONG(
24470 log_write_max_size, srv_log_write_max_size, PLUGIN_VAR_RQCMDARG,
24471 "Size available for next write, which satisfies log_writer thread"
24472 " when it follows links in recent written buffer.",
24473 NULL, NULL, INNODB_LOG_WRITE_MAX_SIZE_DEFAULT, 0, ULONG_MAX,
24474 OS_FILE_LOG_BLOCK_SIZE);
24475
24476 static MYSQL_SYSVAR_ULONG(
24477 log_writer_spin_delay, srv_log_writer_spin_delay, PLUGIN_VAR_RQCMDARG,
24478 "Number of spin iterations, for which log writer thread is waiting"
24479 " for new data to write without sleeping.",
24480 NULL, NULL, INNODB_LOG_WRITER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
24481
24482 extern ulong srv_log_writer_timeout;
24483 static MYSQL_SYSVAR_ULONG(
24484 log_writer_timeout, srv_log_writer_timeout, PLUGIN_VAR_RQCMDARG,
24485 "Initial timeout used to wait on event in log writer thread (microseconds)",
24486 NULL, NULL, INNODB_LOG_WRITER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
24487
24488 extern ulong srv_log_checkpoint_every;
24489 static MYSQL_SYSVAR_ULONG(
24490 log_checkpoint_every, srv_log_checkpoint_every, PLUGIN_VAR_RQCMDARG,
24491 "Checkpoints are executed at least every that many milliseconds.", NULL,
24492 NULL, INNODB_LOG_CHECKPOINT_EVERY_DEFAULT, 0, ULONG_MAX, 0);
24493
24494 static MYSQL_SYSVAR_ULONG(
24495 log_flusher_spin_delay, srv_log_flusher_spin_delay, PLUGIN_VAR_RQCMDARG,
24496 "Number of spin iterations, for which log flusher thread is waiting"
24497 " for new data to flush, without sleeping.",
24498 NULL, NULL, INNODB_LOG_FLUSHER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
24499
24500 extern ulong srv_log_flusher_timeout;
24501 static MYSQL_SYSVAR_ULONG(log_flusher_timeout, srv_log_flusher_timeout,
24502 PLUGIN_VAR_RQCMDARG,
24503 "Initial timeout used to wait on event in log "
24504 "flusher thread (microseconds)",
24505 NULL, NULL, INNODB_LOG_FLUSHER_TIMEOUT_DEFAULT, 0,
24506 ULONG_MAX, 0);
24507
24508 static MYSQL_SYSVAR_ULONG(
24509 log_write_notifier_spin_delay, srv_log_write_notifier_spin_delay,
24510 PLUGIN_VAR_RQCMDARG,
24511 "Number of spin iterations, for which log write notifier thread is waiting"
24512 " for advanced write_lsn, without sleeping.",
24513 NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
24514
24515 extern ulong srv_log_write_notifier_timeout;
24516 static MYSQL_SYSVAR_ULONG(
24517 log_write_notifier_timeout, srv_log_write_notifier_timeout,
24518 PLUGIN_VAR_RQCMDARG,
24519 "Initial timeout used to wait on event in log write notifier thread"
24520 " (microseconds)",
24521 NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
24522
24523 static MYSQL_SYSVAR_ULONG(
24524 log_flush_notifier_spin_delay, srv_log_flush_notifier_spin_delay,
24525 PLUGIN_VAR_RQCMDARG,
24526 "Number of spin iterations, for which log flush notifier thread is waiting"
24527 " for advanced flushed_to_disk_lsn, without sleeping.",
24528 NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0);
24529
24530 extern ulong srv_log_flush_notifier_timeout;
24531 static MYSQL_SYSVAR_ULONG(
24532 log_flush_notifier_timeout, srv_log_flush_notifier_timeout,
24533 PLUGIN_VAR_RQCMDARG,
24534 "Initial timeout used to wait on event in log flush notifier thread"
24535 " (microseconds)",
24536 NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0);
24537
24538 #endif /* ENABLE_EXPERIMENT_SYSVARS */
24539
24540 static MYSQL_SYSVAR_UINT(
24541 old_blocks_pct, innobase_old_blocks_pct, PLUGIN_VAR_RQCMDARG,
24542 "Percentage of the buffer pool to reserve for 'old' blocks.", nullptr,
24543 innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0);
24544
24545 extern uint buf_LRU_old_threshold;
24546 static MYSQL_SYSVAR_UINT(
24547 old_blocks_time, buf_LRU_old_threshold, PLUGIN_VAR_RQCMDARG,
24548 "Move blocks to the 'new' end of the buffer pool if the first access"
24549 " was at least this many milliseconds ago."
24550 " The timeout is disabled if 0.",
24551 nullptr, nullptr, 1000, 0, UINT_MAX32, 0);
24552
24553 static MYSQL_SYSVAR_LONG(
24554 open_files, innobase_open_files, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24555 "How many files at the maximum InnoDB keeps open at the same time.",
24556 nullptr, nullptr, 0L, 0L, LONG_MAX, 0);
24557
24558 static MYSQL_SYSVAR_ULONG(
24559 sync_spin_loops, srv_n_spin_wait_rounds, PLUGIN_VAR_RQCMDARG,
24560 "Count of spin-loop rounds in InnoDB mutexes (30 by default)", nullptr,
24561 nullptr, 30L, 0L, ~0UL, 0);
24562
24563 static MYSQL_SYSVAR_ULONG(
24564 spin_wait_delay, srv_spin_wait_delay, PLUGIN_VAR_OPCMDARG,
24565 "Maximum delay between polling for a spin lock (6 by default)", nullptr,
24566 nullptr, 6L, 0L, 1000, 0);
24567
24568 static MYSQL_SYSVAR_ULONG(spin_wait_pause_multiplier,
24569 ut::spin_wait_pause_multiplier, PLUGIN_VAR_RQCMDARG,
24570 "Controls how many times in a row to use a PAUSE "
24571 "instruction to achieve one unit of delay in a spin "
24572 "lock (see @@innodb_spin_wait_delay), defaults to 50",
24573 nullptr, nullptr, 50, 0, 100, 0);
24574
24575 static MYSQL_SYSVAR_ULONGLONG(
24576 fsync_threshold, os_fsync_threshold, PLUGIN_VAR_RQCMDARG,
24577 "The value of this variable determines how often InnoDB calls fsync when "
24578 "creating a new file. Default is zero which would make InnoDB flush the "
24579 "entire file at once before closing it.",
24580 nullptr, nullptr, 0, 0, ~0ULL, UNIV_PAGE_SIZE);
24581
24582 static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
24583 PLUGIN_VAR_RQCMDARG,
24584 "Helps in performance tuning in heavily concurrent "
24585 "environments. Sets the maximum number of threads "
24586 "allowed inside InnoDB. Value 0 will disable the "
24587 "thread throttling.",
24588 nullptr, innodb_thread_concurrency_update, 0, 0, 1000,
24589 0);
24590
24591 static MYSQL_SYSVAR_ULONG(
24592 adaptive_max_sleep_delay, srv_adaptive_max_sleep_delay, PLUGIN_VAR_RQCMDARG,
24593 "The upper limit of the sleep delay in usec. Value of 0 disables it.",
24594 nullptr, nullptr, 150000, /* Default setting */
24595 0, /* Minimum value */
24596 1000000, 0); /* Maximum value */
24597
24598 static MYSQL_SYSVAR_ULONG(
24599 thread_sleep_delay, srv_thread_sleep_delay, PLUGIN_VAR_RQCMDARG,
24600 "Time of innodb thread sleeping before joining InnoDB queue (usec)."
24601 " Value 0 disable a sleep",
24602 nullptr, nullptr, 10000L, 0L, 1000000L, 0);
24603
24604 static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path,
24605 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
24606 PLUGIN_VAR_NOPERSIST,
24607 "Path to individual files and their sizes.", nullptr,
24608 nullptr, (char *)"ibdata1:12M:autoextend");
24609
24610 static MYSQL_SYSVAR_STR(temp_data_file_path, innobase_temp_data_file_path,
24611 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
24612 PLUGIN_VAR_NOPERSIST,
24613 "Path to files and their sizes making temp-tablespace.",
24614 nullptr, nullptr, (char *)"ibtmp1:12M:autoextend");
24615
24616 static MYSQL_SYSVAR_BOOL(
24617 temp_tablespace_encrypt, srv_tmp_tablespace_encrypt, PLUGIN_VAR_OPCMDARG,
24618 "Enable or disable encryption of temporary tablespace.", nullptr,
24619 innodb_temp_tablespace_encryption_update, false);
24620
24621 static MYSQL_SYSVAR_ENUM(
24622 sys_tablespace_encrypt, srv_sys_tablespace_encrypt,
24623 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
24624 "Enable this option at bootstrap to encrypt system tablespace."
24625 "Set it to RE_ENCRYPTING_TO_KEYRING to allow re-encryption to KEYRING.",
24626 innodb_sys_tablespace_encyption_validate, nullptr,
24627 SYS_TABLESPACE_ENCRYPT_OFF, &sys_tablespace_encrypt_typelib);
24628
24629 static MYSQL_SYSVAR_STR(
24630 undo_directory, srv_undo_dir,
24631 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
24632 "Directory where undo tablespace files live, this path can be absolute.",
24633 nullptr, nullptr, nullptr);
24634
24635 static MYSQL_SYSVAR_STR(
24636 temp_tablespaces_dir, ibt::srv_temp_dir,
24637 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
24638 "Directory where temp tablespace files live, this path can be absolute.",
24639 nullptr, nullptr, nullptr);
24640
24641 static MYSQL_SYSVAR_ULONG(undo_tablespaces, srv_undo_tablespaces,
24642 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST,
24643 "Number of undo tablespaces to use. (deprecated)",
24644 nullptr, innodb_undo_tablespaces_update,
24645 FSP_IMPLICIT_UNDO_TABLESPACES, /* Default seting */
24646 FSP_MIN_UNDO_TABLESPACES, /* Minimum value */
24647 FSP_MAX_UNDO_TABLESPACES, 0); /* Maximum value */
24648
24649 static MYSQL_SYSVAR_ULONGLONG(
24650 max_undo_log_size, srv_max_undo_tablespace_size, PLUGIN_VAR_OPCMDARG,
24651 "Maximum size of an UNDO tablespace in MB (If an UNDO tablespace grows"
24652 " beyond this size it will be truncated in due course). ",
24653 nullptr, nullptr, 1024 * 1024 * 1024L, 10 * 1024 * 1024L, ~0ULL, 0);
24654
24655 static MYSQL_SYSVAR_ULONG(
24656 purge_rseg_truncate_frequency, srv_purge_rseg_truncate_frequency,
24657 PLUGIN_VAR_OPCMDARG,
24658 "Dictates rate at which UNDO records are purged. Value N means"
24659 " purge rollback segment(s) on every Nth iteration of purge invocation",
24660 nullptr, nullptr, 128, 1, 128, 0);
24661
24662 static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate,
24663 PLUGIN_VAR_OPCMDARG,
24664 "Enable or Disable Truncate of UNDO tablespace.",
24665 nullptr, nullptr, true);
24666
24667 /* This is the number of rollback segments per undo tablespace.
24668 This applies to the temporary tablespace, the system tablespace,
24669 and all undo tablespaces. */
24670 static MYSQL_SYSVAR_ULONG(
24671 rollback_segments, srv_rollback_segments, PLUGIN_VAR_OPCMDARG,
24672 "Number of rollback segments per tablespace. This applies to the system"
24673 " tablespace, the temporary tablespace & any undo tablespace.",
24674 nullptr, innodb_rollback_segments_update,
24675 FSP_MAX_ROLLBACK_SEGMENTS, /* Default setting */
24676 1, /* Minimum value */
24677 FSP_MAX_ROLLBACK_SEGMENTS, 0); /* Maximum value */
24678
24679 static MYSQL_SYSVAR_BOOL(undo_log_encrypt, srv_undo_log_encrypt,
24680 PLUGIN_VAR_OPCMDARG,
24681 "Enable or disable Encrypt of UNDO tablespace.",
24682 validate_innodb_undo_log_encrypt, nullptr, false);
24683
24684 static MYSQL_SYSVAR_LONG(
24685 autoinc_lock_mode, innobase_autoinc_lock_mode,
24686 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
24687 "The AUTOINC lock modes supported by InnoDB:"
24688 " 0 => Old style AUTOINC locking (for backward compatibility);"
24689 " 1 => New style AUTOINC locking;"
24690 " 2 => No AUTOINC locking (unsafe for SBR)",
24691 nullptr, nullptr, AUTOINC_NO_LOCKING, /* Default setting */
24692 AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */
24693 AUTOINC_NO_LOCKING, 0); /* Maximum value */
24694
24695 static MYSQL_SYSVAR_STR(version, innodb_version_str,
24696 PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY |
24697 PLUGIN_VAR_NOPERSIST,
24698 "InnoDB version", nullptr, nullptr, INNODB_VERSION_STR);
24699
24700 static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio,
24701 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
24702 "Use native AIO if supported on this platform.",
24703 nullptr, nullptr, true);
24704
24705 #ifdef HAVE_LIBNUMA
24706 static MYSQL_SYSVAR_BOOL(
24707 numa_interleave, srv_numa_interleave,
24708 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
24709 "Use NUMA interleave memory policy to allocate InnoDB buffer pool.",
24710 nullptr, nullptr, false);
24711 #endif /* HAVE_LIBNUMA */
24712
24713 static MYSQL_SYSVAR_BOOL(
24714 api_enable_binlog, ib_binlog_enabled,
24715 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
24716 "Enable binlog for applications direct access InnoDB through InnoDB APIs",
24717 nullptr, nullptr, false);
24718
24719 static MYSQL_SYSVAR_BOOL(
24720 api_enable_mdl, ib_mdl_enabled, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
24721 "Enable MDL for applications direct access InnoDB through InnoDB APIs",
24722 nullptr, nullptr, false);
24723
24724 static MYSQL_SYSVAR_BOOL(
24725 api_disable_rowlock, ib_disable_row_lock,
24726 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
24727 "Disable row lock when direct access InnoDB through InnoDB APIs", nullptr,
24728 nullptr, false);
24729
24730 static MYSQL_SYSVAR_ULONG(api_trx_level, ib_trx_level_setting,
24731 PLUGIN_VAR_OPCMDARG,
24732 "InnoDB API transaction isolation level", nullptr,
24733 nullptr, 0, /* Default setting */
24734 0, /* Minimum value */
24735 3, 0); /* Maximum value */
24736
24737 static MYSQL_SYSVAR_ULONG(api_bk_commit_interval, ib_bk_commit_interval,
24738 PLUGIN_VAR_OPCMDARG,
24739 "Background commit interval in seconds", nullptr,
24740 nullptr, 5, /* Default setting */
24741 1, /* Minimum value */
24742 1024 * 1024 * 1024, 0); /* Maximum value */
24743
24744 static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering,
24745 PLUGIN_VAR_RQCMDARG,
24746 "Buffer changes to reduce random access:"
24747 " OFF, ON, inserting, deleting, changing, or purging.",
24748 nullptr, nullptr, IBUF_USE_ALL,
24749 &innodb_change_buffering_typelib);
24750
24751 static MYSQL_SYSVAR_UINT(
24752 change_buffer_max_size, srv_change_buffer_max_size, PLUGIN_VAR_RQCMDARG,
24753 "Maximum on-disk size of change buffer in terms of percentage"
24754 " of the buffer pool.",
24755 nullptr, innodb_change_buffer_max_size_update, CHANGE_BUFFER_DEFAULT_SIZE,
24756 0, 50, 0);
24757
24758 static MYSQL_SYSVAR_ENUM(
24759 stats_method, srv_innodb_stats_method, PLUGIN_VAR_RQCMDARG,
24760 "Specifies how InnoDB index statistics collection code should"
24761 " treat NULLs. Possible values are NULLS_EQUAL (default),"
24762 " NULLS_UNEQUAL and NULLS_IGNORED",
24763 nullptr, nullptr, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
24764
24765 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
24766 static MYSQL_SYSVAR_UINT(
24767 change_buffering_debug, ibuf_debug, PLUGIN_VAR_RQCMDARG,
24768 "Debug flags for InnoDB change buffering (0=none, 2=crash at merge)",
24769 nullptr, nullptr, 0, 0, 2, 0);
24770
24771 static MYSQL_SYSVAR_BOOL(disable_background_merge,
24772 srv_ibuf_disable_background_merge,
24773 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_RQCMDARG,
24774 "Disable change buffering merges by the master thread",
24775 nullptr, nullptr, false);
24776
24777 static MYSQL_SYSVAR_ENUM(
24778 compress_debug, srv_debug_compress, PLUGIN_VAR_RQCMDARG,
24779 "Compress all tables, without specifying the COMPRESS table attribute",
24780 nullptr, nullptr, Compression::NONE, &innodb_debug_compress_typelib);
24781 #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
24782
24783 static MYSQL_SYSVAR_BOOL(
24784 random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG,
24785 "Whether to use read ahead for random access within an extent.", nullptr,
24786 nullptr, false);
24787
24788 static MYSQL_SYSVAR_ULONG(
24789 read_ahead_threshold, srv_read_ahead_threshold, PLUGIN_VAR_RQCMDARG,
24790 "Number of pages that must be accessed sequentially for InnoDB to"
24791 " trigger a readahead.",
24792 nullptr, nullptr, 56, 0, 64, 0);
24793
24794 static MYSQL_SYSVAR_STR(monitor_enable, innobase_enable_monitor_counter,
24795 PLUGIN_VAR_RQCMDARG, "Turn on a monitor counter",
24796 innodb_monitor_validate, innodb_enable_monitor_update,
24797 nullptr);
24798
24799 static MYSQL_SYSVAR_STR(monitor_disable, innobase_disable_monitor_counter,
24800 PLUGIN_VAR_RQCMDARG, "Turn off a monitor counter",
24801 innodb_monitor_validate, innodb_disable_monitor_update,
24802 nullptr);
24803
24804 static MYSQL_SYSVAR_STR(monitor_reset, innobase_reset_monitor_counter,
24805 PLUGIN_VAR_RQCMDARG, "Reset a monitor counter",
24806 innodb_monitor_validate, innodb_reset_monitor_update,
24807 nullptr);
24808
24809 static MYSQL_SYSVAR_STR(monitor_reset_all, innobase_reset_all_monitor_counter,
24810 PLUGIN_VAR_RQCMDARG,
24811 "Reset all values for a monitor counter",
24812 innodb_monitor_validate,
24813 innodb_reset_all_monitor_update, nullptr);
24814
24815 static MYSQL_SYSVAR_BOOL(status_output, srv_print_innodb_monitor,
24816 PLUGIN_VAR_OPCMDARG,
24817 "Enable InnoDB monitor output to the error log.",
24818 nullptr, nullptr, false);
24819
24820 static MYSQL_SYSVAR_BOOL(status_output_locks, srv_print_innodb_lock_monitor,
24821 PLUGIN_VAR_OPCMDARG,
24822 "Enable InnoDB lock monitor output to the error log."
24823 " Requires innodb_status_output=ON.",
24824 nullptr, nullptr, false);
24825
24826 static MYSQL_SYSVAR_BOOL(
24827 print_all_deadlocks, srv_print_all_deadlocks, PLUGIN_VAR_OPCMDARG,
24828 "Print all deadlocks to MySQL error log (off by default)", nullptr, nullptr,
24829 false);
24830
24831 static MYSQL_SYSVAR_BOOL(
24832 print_lock_wait_timeout_info, srv_print_lock_wait_timeout_info,
24833 PLUGIN_VAR_OPCMDARG,
24834 "Print lock wait timeout info to MySQL error log (off by default)", nullptr,
24835 nullptr, false);
24836
24837 static MYSQL_SYSVAR_ULONG(
24838 compression_failure_threshold_pct, zip_failure_threshold_pct,
24839 PLUGIN_VAR_OPCMDARG,
24840 "If the compression failure rate of a table is greater than this number"
24841 " more padding is added to the pages to reduce the failures. A value of"
24842 " zero implies no padding",
24843 nullptr, nullptr, 5, 0, 100, 0);
24844
24845 static MYSQL_SYSVAR_ULONG(
24846 compression_pad_pct_max, zip_pad_max, PLUGIN_VAR_OPCMDARG,
24847 "Percentage of empty space on a data page that can be reserved"
24848 " to make the page compressible.",
24849 nullptr, nullptr, 50, 0, 75, 0);
24850
24851 static MYSQL_SYSVAR_BOOL(read_only, srv_read_only_mode,
24852 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY |
24853 PLUGIN_VAR_NOPERSIST,
24854 "Start InnoDB in read only mode (off by default)",
24855 nullptr, nullptr, false);
24856
24857 static MYSQL_SYSVAR_BOOL(
24858 cmp_per_index_enabled, srv_cmp_per_index_enabled, PLUGIN_VAR_OPCMDARG,
24859 "Enable INFORMATION_SCHEMA.innodb_cmp_per_index,"
24860 " may have negative impact on performance (off by default)",
24861 nullptr, innodb_cmp_per_index_update, false);
24862
24863 static MYSQL_SYSVAR_ENUM(
24864 default_row_format, innodb_default_row_format, PLUGIN_VAR_RQCMDARG,
24865 "The default ROW FORMAT for all innodb tables created without explicit"
24866 " ROW_FORMAT. Possible values are REDUNDANT, COMPACT, and DYNAMIC."
24867 " The ROW_FORMAT value COMPRESSED is not allowed",
24868 nullptr, nullptr, DEFAULT_ROW_FORMAT_DYNAMIC,
24869 &innodb_default_row_format_typelib);
24870
24871 static MYSQL_SYSVAR_STR(
24872 redo_log_archive_dirs, meb::redo_log_archive_dirs,
24873 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
24874 "Limit the location of the redo log archive to the semicolon "
24875 "separated list of labeled directories",
24876 /*validate_func*/ meb::validate_redo_log_archive_dirs,
24877 /*update_func*/ nullptr, /*default*/ nullptr);
24878
24879 static MYSQL_SYSVAR_BOOL(redo_log_encrypt, srv_redo_log_encrypt,
24880 PLUGIN_VAR_OPCMDARG,
24881 "Enable or disable Encryption of REDO tablespace.",
24882 validate_innodb_redo_log_encrypt, nullptr, false);
24883
24884 static MYSQL_SYSVAR_BOOL(
24885 print_ddl_logs, srv_print_ddl_logs, PLUGIN_VAR_OPCMDARG,
24886 "Print all DDl logs to MySQL error log (off by default)", nullptr, nullptr,
24887 false);
24888
24889 #ifdef UNIV_DEBUG
24890 static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
24891 PLUGIN_VAR_RQCMDARG,
24892 "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for "
24893 "trx_rsegf_undo_find_free()",
24894 nullptr, nullptr, 0, 0, 1024, 0);
24895
24896 static MYSQL_SYSVAR_UINT(
24897 limit_optimistic_insert_debug, btr_cur_limit_optimistic_insert_debug,
24898 PLUGIN_VAR_RQCMDARG,
24899 "Artificially limit the number of records per B-tree page (0=unlimited).",
24900 nullptr, nullptr, 0, 0, UINT_MAX32, 0);
24901
24902 static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug,
24903 srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDARG,
24904 "Pause actual purging any delete-marked records, but "
24905 "merely update the purge view."
24906 " It is to create artificially the situation the "
24907 "purge view have been updated"
24908 " but the each purges were not done yet.",
24909 nullptr, nullptr, false);
24910 // clang-format off
24911 static MYSQL_SYSVAR_ULONG(
24912 fil_make_page_dirty_debug,
24913 srv_fil_make_page_dirty_debug, PLUGIN_VAR_OPCMDARG,
24914 "Make the first page of the given tablespace dirty.",
24915 nullptr, innodb_make_page_dirty, UINT_MAX32, 0, UINT_MAX32, 0);
24916 // clang-format on
24917
24918 static MYSQL_SYSVAR_ULONG(saved_page_number_debug, srv_saved_page_number_debug,
24919 PLUGIN_VAR_OPCMDARG, "An InnoDB page number.",
24920 nullptr, innodb_save_page_no, 0, 0, UINT_MAX32, 0);
24921
24922 static MYSQL_SYSVAR_BOOL(page_cleaner_disabled_debug,
24923 innodb_page_cleaner_disabled_debug,
24924 PLUGIN_VAR_OPCMDARG, "Disable page cleaner", nullptr,
24925 buf_flush_page_cleaner_disabled_debug_update, false);
24926
24927 static MYSQL_SYSVAR_BOOL(dict_stats_disabled_debug,
24928 innodb_dict_stats_disabled_debug, PLUGIN_VAR_OPCMDARG,
24929 "Disable dict_stats thread", nullptr,
24930 dict_stats_disabled_debug_update, false);
24931
24932 static MYSQL_SYSVAR_BOOL(master_thread_disabled_debug,
24933 srv_master_thread_disabled_debug, PLUGIN_VAR_OPCMDARG,
24934 "Disable master thread", nullptr,
24935 srv_master_thread_disabled_debug_update, false);
24936
24937 static MYSQL_SYSVAR_BOOL(sync_debug, srv_sync_debug,
24938 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
24939 "Enable the sync debug checks", nullptr, nullptr,
24940 false);
24941
24942 static MYSQL_SYSVAR_BOOL(buffer_pool_debug, srv_buf_pool_debug,
24943 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
24944 "Enable buffer pool debug", nullptr, nullptr, false);
24945
24946 static MYSQL_SYSVAR_BOOL(ddl_log_crash_reset_debug,
24947 innodb_ddl_log_crash_reset_debug, PLUGIN_VAR_OPCMDARG,
24948 "Reset all crash injection counters to 1", nullptr,
24949 ddl_log_crash_reset, false);
24950
24951 #endif /* UNIV_DEBUG */
24952
24953 static MYSQL_SYSVAR_STR(directories, srv_innodb_directories,
24954 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY |
24955 PLUGIN_VAR_NOPERSIST,
24956 "List of directories 'dir1;dir2;..;dirN' to scan for "
24957 "tablespace files. Default is to scan "
24958 "'innodb-data-home-dir;innodb-undo-directory;datadir'",
24959 nullptr, nullptr, nullptr);
24960
24961 #ifdef UNIV_DEBUG
24962 /** Use this variable innodb_interpreter to execute debug code within InnoDB.
24963 The output is stored in the innodb_interpreter_output variable. */
24964 static MYSQL_THDVAR_STR(interpreter, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
24965 "Invoke InnoDB test interpreter with commands"
24966 " to be executed.",
24967 ib_interpreter_check, ib_interpreter_update, "init");
24968
24969 /** When testing commands are executed in the innodb_interpreter variable, the
24970 output is stored in this innodb_interpreter_output variable. */
24971 static MYSQL_THDVAR_STR(interpreter_output,
24972 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC |
24973 PLUGIN_VAR_NOPERSIST,
24974 "Output from InnoDB testing module (ut0test).", nullptr,
24975 nullptr, "The Default Value");
24976
24977 54 char **thd_innodb_interpreter_output(THD *thd) {
24978 return (MYSQL_SYSVAR_NAME(interpreter_output)
24979 54 .resolve(thd, MYSQL_SYSVAR_NAME(interpreter_output).offset));
24980 }
24981
24982 54 char **thd_innodb_interpreter(THD *thd) {
24983 return MYSQL_SYSVAR_NAME(interpreter)
24984 54 .resolve(thd, MYSQL_SYSVAR_NAME(interpreter).offset);
24985 }
24986 #endif /* UNIV_DEBUG */
24987
24988 static const char *corrupt_table_action_names[] = {"assert", /* 0 */
24989 "warn", /* 1 */
24990 "salvage", /* 2 */
24991 NullS};
24992
24993 static TYPELIB corrupt_table_action_typelib = {
24994 array_elements(corrupt_table_action_names) - 1,
24995 "corrupt_table_action_typelib", corrupt_table_action_names, nullptr};
24996
24997 static MYSQL_SYSVAR_ENUM(
24998 corrupt_table_action, srv_pass_corrupt_table, PLUGIN_VAR_RQCMDARG,
24999 "Warn corruptions of user tables as 'corrupt table' instead of not "
25000 "crashing itself, "
25001 "when used with file_per_table. "
25002 "All file io for the datafile after detected as corrupt are disabled, "
25003 "except for the deletion.",
25004 nullptr, nullptr, 0, &corrupt_table_action_typelib);
25005
25006 static MYSQL_SYSVAR_STR(
25007 parallel_doublewrite_path, srv_parallel_doublewrite_path_deprecated,
25008 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST,
25009 "Deprecated Percona-specific variable that was used to set path to the "
25010 "parallel doublewrite file and has no effect now. "
25011 "Use --innodb-doublewrite-dir instead.",
25012 nullptr, innodb_parallel_doublewrite_path_update, "xb_doublewrite");
25013
25014 static MYSQL_SYSVAR_BOOL(
25015 parallel_dblwr_encrypt, srv_parallel_dblwr_encrypt_deprecated,
25016 PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST,
25017 "Deprecated Percona-specific variable that was used to enable or "
25018 "disable encryption of parallel doublewrite buffer file and has no "
25019 "effect now.",
25020 nullptr, innodb_parallel_dblwr_encrypt_update, false);
25021
25022 static MYSQL_SYSVAR_UINT(
25023 compressed_columns_zip_level, srv_compressed_columns_zip_level,
25024 PLUGIN_VAR_RQCMDARG,
25025 "Compression level used for compressed columns. 0 is no compression"
25026 ", 1 is fastest and 9 is best compression. Default is 6.",
25027 nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0);
25028
25029 static MYSQL_SYSVAR_ULONG(
25030 compressed_columns_threshold, srv_compressed_columns_threshold,
25031 PLUGIN_VAR_RQCMDARG,
25032 "Compress column data if its length exceeds this value. Default is 96",
25033 nullptr, nullptr, 96, 1, ~0UL, 0);
25034
25035 static MYSQL_SYSVAR_BOOL(encrypt_online_alter_logs,
25036 srv_encrypt_online_alter_logs,
25037 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
25038 "Encrypt online alter logs.", nullptr, nullptr, false);
25039
25040 static MYSQL_SYSVAR_UINT(
25041 encryption_threads, srv_n_fil_crypt_threads_requested, PLUGIN_VAR_RQCMDARG,
25042 "Number of threads performing background key rotation and "
25043 "scrubbing",
25044 innodb_encryption_threads_validate, innodb_encryption_threads_update, 0, 0,
25045 MAX_ENCRYPTION_THREADS, 0);
25046
25047 static MYSQL_SYSVAR_UINT(encryption_rotate_key_age,
25048 srv_fil_crypt_rotate_key_age, PLUGIN_VAR_RQCMDARG,
25049 "Key rotation - re-encrypt in background "
25050 "all pages that were encrypted with a key that "
25051 "many (or more) versions behind. Value 0 indicates "
25052 "that key rotation is disabled.",
25053 NULL, innodb_encryption_rotate_key_age_update, 1, 0,
25054 UINT_MAX32, 0);
25055
25056 static MYSQL_SYSVAR_UINT(encryption_rotation_iops, srv_n_fil_crypt_iops,
25057 PLUGIN_VAR_RQCMDARG,
25058 "Use this many iops for background key rotation", NULL,
25059 innodb_encryption_rotation_iops_update,
25060 srv_n_fil_crypt_iops, 0, UINT_MAX32, 0);
25061
25062 static SYS_VAR *innobase_system_variables[] = {
25063 MYSQL_SYSVAR(api_trx_level),
25064 MYSQL_SYSVAR(api_bk_commit_interval),
25065 MYSQL_SYSVAR(autoextend_increment),
25066 MYSQL_SYSVAR(dedicated_server),
25067 MYSQL_SYSVAR(buffer_pool_size),
25068 MYSQL_SYSVAR(buffer_pool_chunk_size),
25069 MYSQL_SYSVAR(buffer_pool_instances),
25070 MYSQL_SYSVAR(buffer_pool_filename),
25071 MYSQL_SYSVAR(buffer_pool_dump_now),
25072 MYSQL_SYSVAR(buffer_pool_dump_at_shutdown),
25073 MYSQL_SYSVAR(buffer_pool_in_core_file),
25074 MYSQL_SYSVAR(buffer_pool_dump_pct),
25075 #ifdef UNIV_DEBUG
25076 MYSQL_SYSVAR(buffer_pool_evict),
25077 #endif /* UNIV_DEBUG */
25078 MYSQL_SYSVAR(buffer_pool_load_now),
25079 MYSQL_SYSVAR(buffer_pool_load_abort),
25080 MYSQL_SYSVAR(buffer_pool_load_at_startup),
25081 MYSQL_SYSVAR(lru_scan_depth),
25082 MYSQL_SYSVAR(flush_neighbors),
25083 MYSQL_SYSVAR(checksum_algorithm),
25084 MYSQL_SYSVAR(log_checksums),
25085 MYSQL_SYSVAR(commit_concurrency),
25086 MYSQL_SYSVAR(concurrency_tickets),
25087 MYSQL_SYSVAR(compression_level),
25088 MYSQL_SYSVAR(ddl_buffer_size),
25089 MYSQL_SYSVAR(ddl_threads),
25090 MYSQL_SYSVAR(data_file_path),
25091 MYSQL_SYSVAR(temp_data_file_path),
25092 MYSQL_SYSVAR(temp_tablespace_encrypt),
25093 MYSQL_SYSVAR(sys_tablespace_encrypt),
25094 MYSQL_SYSVAR(data_home_dir),
25095 MYSQL_SYSVAR(extend_and_initialize),
25096 MYSQL_SYSVAR(doublewrite),
25097 MYSQL_SYSVAR(doublewrite_dir),
25098 MYSQL_SYSVAR(doublewrite_batch_size),
25099 MYSQL_SYSVAR(doublewrite_files),
25100 MYSQL_SYSVAR(doublewrite_pages),
25101 MYSQL_SYSVAR(stats_include_delete_marked),
25102 MYSQL_SYSVAR(api_enable_binlog),
25103 MYSQL_SYSVAR(api_enable_mdl),
25104 MYSQL_SYSVAR(api_disable_rowlock),
25105 MYSQL_SYSVAR(fast_shutdown),
25106 MYSQL_SYSVAR(read_io_threads),
25107 MYSQL_SYSVAR(write_io_threads),
25108 MYSQL_SYSVAR(file_per_table),
25109 MYSQL_SYSVAR(flush_log_at_timeout),
25110 MYSQL_SYSVAR(flush_log_at_trx_commit),
25111 MYSQL_SYSVAR(flush_method),
25112 MYSQL_SYSVAR(force_recovery),
25113 #ifdef UNIV_DEBUG
25114 MYSQL_SYSVAR(force_recovery_crash),
25115 #endif /* UNIV_DEBUG */
25116 MYSQL_SYSVAR(fill_factor),
25117 MYSQL_SYSVAR(ft_cache_size),
25118 MYSQL_SYSVAR(ft_total_cache_size),
25119 MYSQL_SYSVAR(ft_result_cache_limit),
25120 MYSQL_SYSVAR(ft_enable_stopword),
25121 MYSQL_SYSVAR(ft_max_token_size),
25122 MYSQL_SYSVAR(ft_min_token_size),
25123 MYSQL_SYSVAR(ft_num_word_optimize),
25124 MYSQL_SYSVAR(ft_sort_pll_degree),
25125 MYSQL_SYSVAR(force_load_corrupted),
25126 MYSQL_SYSVAR(lock_wait_timeout),
25127 MYSQL_SYSVAR(deadlock_detect),
25128 MYSQL_SYSVAR(page_size),
25129 MYSQL_SYSVAR(log_buffer_size),
25130 MYSQL_SYSVAR(log_file_size),
25131 MYSQL_SYSVAR(log_files_in_group),
25132 MYSQL_SYSVAR(redo_log_capacity),
25133 #ifdef UNIV_DEBUG_DEDICATED
25134 MYSQL_SYSVAR(debug_sys_mem_size),
25135 #endif /* UNIV_DEBUG_DEDICATED */
25136 MYSQL_SYSVAR(log_write_ahead_size),
25137 MYSQL_SYSVAR(log_group_home_dir),
25138 MYSQL_SYSVAR(log_writer_threads),
25139 MYSQL_SYSVAR(log_spin_cpu_abs_lwm),
25140 MYSQL_SYSVAR(log_spin_cpu_pct_hwm),
25141 MYSQL_SYSVAR(log_wait_for_flush_spin_hwm),
25142 #ifdef ENABLE_EXPERIMENT_SYSVARS
25143 MYSQL_SYSVAR(log_write_events),
25144 MYSQL_SYSVAR(log_flush_events),
25145 MYSQL_SYSVAR(log_recent_written_size),
25146 MYSQL_SYSVAR(log_recent_closed_size),
25147 MYSQL_SYSVAR(log_wait_for_write_spin_delay),
25148 MYSQL_SYSVAR(log_wait_for_write_timeout),
25149 MYSQL_SYSVAR(log_wait_for_flush_spin_delay),
25150 MYSQL_SYSVAR(log_wait_for_flush_timeout),
25151 MYSQL_SYSVAR(log_write_max_size),
25152 MYSQL_SYSVAR(log_writer_spin_delay),
25153 MYSQL_SYSVAR(log_writer_timeout),
25154 MYSQL_SYSVAR(log_checkpoint_every),
25155 MYSQL_SYSVAR(log_flusher_spin_delay),
25156 MYSQL_SYSVAR(log_flusher_timeout),
25157 MYSQL_SYSVAR(log_write_notifier_spin_delay),
25158 MYSQL_SYSVAR(log_write_notifier_timeout),
25159 MYSQL_SYSVAR(log_flush_notifier_spin_delay),
25160 MYSQL_SYSVAR(log_flush_notifier_timeout),
25161 #endif /* ENABLE_EXPERIMENT_SYSVARS */
25162 MYSQL_SYSVAR(log_compressed_pages),
25163 MYSQL_SYSVAR(max_dirty_pages_pct),
25164 MYSQL_SYSVAR(max_dirty_pages_pct_lwm),
25165 MYSQL_SYSVAR(adaptive_flushing_lwm),
25166 MYSQL_SYSVAR(adaptive_flushing),
25167 MYSQL_SYSVAR(flush_sync),
25168 MYSQL_SYSVAR(flushing_avg_loops),
25169 MYSQL_SYSVAR(max_purge_lag),
25170 MYSQL_SYSVAR(max_purge_lag_delay),
25171 MYSQL_SYSVAR(old_blocks_pct),
25172 MYSQL_SYSVAR(old_blocks_time),
25173 MYSQL_SYSVAR(open_files),
25174 MYSQL_SYSVAR(optimize_fulltext_only),
25175 MYSQL_SYSVAR(rollback_on_timeout),
25176 MYSQL_SYSVAR(ft_aux_table),
25177 MYSQL_SYSVAR(ft_enable_diag_print),
25178 MYSQL_SYSVAR(ft_server_stopword_table),
25179 MYSQL_SYSVAR(ft_user_stopword_table),
25180 MYSQL_SYSVAR(disable_sort_file_cache),
25181 MYSQL_SYSVAR(stats_on_metadata),
25182 MYSQL_SYSVAR(stats_transient_sample_pages),
25183 MYSQL_SYSVAR(stats_persistent),
25184 MYSQL_SYSVAR(stats_persistent_sample_pages),
25185 MYSQL_SYSVAR(stats_auto_recalc),
25186 MYSQL_SYSVAR(adaptive_hash_index),
25187 MYSQL_SYSVAR(adaptive_hash_index_parts),
25188 MYSQL_SYSVAR(stats_method),
25189 MYSQL_SYSVAR(replication_delay),
25190 MYSQL_SYSVAR(status_file),
25191 MYSQL_SYSVAR(strict_mode),
25192 MYSQL_SYSVAR(sort_buffer_size),
25193 MYSQL_SYSVAR(online_alter_log_max_size),
25194 MYSQL_SYSVAR(directories),
25195 MYSQL_SYSVAR(sync_spin_loops),
25196 MYSQL_SYSVAR(spin_wait_delay),
25197 MYSQL_SYSVAR(spin_wait_pause_multiplier),
25198 MYSQL_SYSVAR(fsync_threshold),
25199 MYSQL_SYSVAR(table_locks),
25200 MYSQL_SYSVAR(thread_concurrency),
25201 MYSQL_SYSVAR(adaptive_max_sleep_delay),
25202 MYSQL_SYSVAR(thread_sleep_delay),
25203 MYSQL_SYSVAR(tmpdir),
25204 MYSQL_SYSVAR(autoinc_lock_mode),
25205 MYSQL_SYSVAR(show_locks_held),
25206 MYSQL_SYSVAR(version),
25207 MYSQL_SYSVAR(use_native_aio),
25208 #ifdef HAVE_LIBNUMA
25209 MYSQL_SYSVAR(numa_interleave),
25210 #endif /* HAVE_LIBNUMA */
25211 MYSQL_SYSVAR(change_buffering),
25212 MYSQL_SYSVAR(change_buffer_max_size),
25213 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
25214 MYSQL_SYSVAR(change_buffering_debug),
25215 MYSQL_SYSVAR(disable_background_merge),
25216 #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
25217 MYSQL_SYSVAR(random_read_ahead),
25218 MYSQL_SYSVAR(read_ahead_threshold),
25219 MYSQL_SYSVAR(read_only),
25220
25221 MYSQL_SYSVAR(io_capacity),
25222 MYSQL_SYSVAR(io_capacity_max),
25223 MYSQL_SYSVAR(idle_flush_pct),
25224 MYSQL_SYSVAR(page_cleaners),
25225 MYSQL_SYSVAR(monitor_enable),
25226 MYSQL_SYSVAR(monitor_disable),
25227 MYSQL_SYSVAR(monitor_reset),
25228 MYSQL_SYSVAR(monitor_reset_all),
25229 MYSQL_SYSVAR(purge_threads),
25230 MYSQL_SYSVAR(purge_batch_size),
25231 #ifdef UNIV_DEBUG
25232 MYSQL_SYSVAR(background_drop_list_empty),
25233 MYSQL_SYSVAR(purge_run_now),
25234 MYSQL_SYSVAR(purge_stop_now),
25235 MYSQL_SYSVAR(log_flush_now),
25236 MYSQL_SYSVAR(log_checkpoint_now),
25237 MYSQL_SYSVAR(log_checkpoint_fuzzy_now),
25238 MYSQL_SYSVAR(checkpoint_disabled),
25239 MYSQL_SYSVAR(buf_flush_list_now),
25240 MYSQL_SYSVAR(merge_threshold_set_all_debug),
25241 MYSQL_SYSVAR(semaphore_wait_timeout_debug),
25242 #endif /* UNIV_DEBUG */
25243 #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG
25244 MYSQL_SYSVAR(page_hash_locks),
25245 #ifdef UNIV_LINUX
25246 MYSQL_SYSVAR(sched_priority_purge),
25247 MYSQL_SYSVAR(sched_priority_io),
25248 MYSQL_SYSVAR(sched_priority_master),
25249 MYSQL_SYSVAR(priority_purge),
25250 MYSQL_SYSVAR(priority_master),
25251 #endif /* UNIV_LINUX */
25252 MYSQL_SYSVAR(cleaner_max_lru_time),
25253 MYSQL_SYSVAR(cleaner_max_flush_time),
25254 #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
25255 MYSQL_SYSVAR(validate_tablespace_paths),
25256 MYSQL_SYSVAR(use_fdatasync),
25257 MYSQL_SYSVAR(status_output),
25258 MYSQL_SYSVAR(status_output_locks),
25259 MYSQL_SYSVAR(cleaner_lsn_age_factor),
25260 MYSQL_SYSVAR(empty_free_list_algorithm),
25261 MYSQL_SYSVAR(print_all_deadlocks),
25262 MYSQL_SYSVAR(print_lock_wait_timeout_info),
25263 MYSQL_SYSVAR(cmp_per_index_enabled),
25264 MYSQL_SYSVAR(max_undo_log_size),
25265 MYSQL_SYSVAR(purge_rseg_truncate_frequency),
25266 MYSQL_SYSVAR(undo_log_truncate),
25267 MYSQL_SYSVAR(undo_log_encrypt),
25268 MYSQL_SYSVAR(rollback_segments),
25269 MYSQL_SYSVAR(undo_directory),
25270 MYSQL_SYSVAR(temp_tablespaces_dir),
25271 MYSQL_SYSVAR(undo_tablespaces),
25272 MYSQL_SYSVAR(sync_array_size),
25273 MYSQL_SYSVAR(compression_failure_threshold_pct),
25274 MYSQL_SYSVAR(compression_pad_pct_max),
25275 MYSQL_SYSVAR(default_row_format),
25276 MYSQL_SYSVAR(redo_log_archive_dirs),
25277 MYSQL_SYSVAR(redo_log_encrypt),
25278 MYSQL_SYSVAR(print_ddl_logs),
25279 #ifdef UNIV_DEBUG
25280 MYSQL_SYSVAR(trx_rseg_n_slots_debug),
25281 MYSQL_SYSVAR(limit_optimistic_insert_debug),
25282 MYSQL_SYSVAR(trx_purge_view_update_only_debug),
25283 MYSQL_SYSVAR(fil_make_page_dirty_debug),
25284 MYSQL_SYSVAR(saved_page_number_debug),
25285 MYSQL_SYSVAR(compress_debug),
25286 MYSQL_SYSVAR(page_cleaner_disabled_debug),
25287 MYSQL_SYSVAR(dict_stats_disabled_debug),
25288 MYSQL_SYSVAR(master_thread_disabled_debug),
25289 MYSQL_SYSVAR(sync_debug),
25290 MYSQL_SYSVAR(buffer_pool_debug),
25291 MYSQL_SYSVAR(ddl_log_crash_reset_debug),
25292 MYSQL_SYSVAR(interpreter),
25293 MYSQL_SYSVAR(interpreter_output),
25294 #endif /* UNIV_DEBUG */
25295 MYSQL_SYSVAR(parallel_read_threads),
25296 MYSQL_SYSVAR(segment_reserve_factor),
25297 MYSQL_SYSVAR(corrupt_table_action),
25298 MYSQL_SYSVAR(parallel_doublewrite_path),
25299 MYSQL_SYSVAR(parallel_dblwr_encrypt),
25300 MYSQL_SYSVAR(compressed_columns_zip_level),
25301 MYSQL_SYSVAR(compressed_columns_threshold),
25302 MYSQL_SYSVAR(ft_ignore_stopwords),
25303 MYSQL_SYSVAR(encrypt_online_alter_logs),
25304 MYSQL_SYSVAR(encryption_threads),
25305 MYSQL_SYSVAR(encryption_rotate_key_age),
25306 MYSQL_SYSVAR(encryption_rotation_iops),
25307 MYSQL_SYSVAR(default_encryption_key_id),
25308 MYSQL_SYSVAR(records_in_range),
25309 MYSQL_SYSVAR(force_index_records_in_range),
25310 nullptr};
25311
25312 mysql_declare_plugin(innobase){
25313 MYSQL_STORAGE_ENGINE_PLUGIN,
25314 &innobase_storage_engine,
25315 innobase_hton_name,
25316 PLUGIN_AUTHOR_ORACLE,
25317 "Percona-XtraDB, Supports transactions, row-level locking, and foreign "
25318 "keys",
25319 PLUGIN_LICENSE_GPL,
25320 innodb_init, /* Plugin Init */
25321 nullptr, /* Plugin Check uninstall */
25322 innodb_deinit, /* Plugin Deinit */
25323 INNODB_VERSION_SHORT,
25324 innodb_status_variables_export, /* status variables */
25325 innobase_system_variables, /* system variables */
25326 nullptr, /* reserved */
25327 0, /* flags */
25328 },
25329 i_s_innodb_trx, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem,
25330 i_s_innodb_cmpmem_reset, i_s_innodb_cmp_per_index,
25331 i_s_innodb_cmp_per_index_reset, i_s_innodb_buffer_page,
25332 i_s_innodb_buffer_page_lru, i_s_innodb_buffer_stats,
25333 i_s_innodb_temp_table_info, i_s_innodb_metrics,
25334 i_s_innodb_ft_default_stopword, i_s_innodb_ft_deleted,
25335 i_s_innodb_ft_being_deleted, i_s_innodb_ft_config,
25336 i_s_innodb_ft_index_cache, i_s_innodb_ft_index_table, i_s_innodb_tables,
25337 i_s_innodb_tablestats, i_s_innodb_indexes, i_s_innodb_tablespaces,
25338 i_s_innodb_columns, i_s_innodb_virtual, i_s_innodb_cached_indexes,
25339 i_s_innodb_session_temp_tablespaces,
25340 i_s_innodb_tablespaces_encryption
25341
25342 mysql_declare_plugin_end;
25343
25344 /** @brief Initialize the default value of innodb_commit_concurrency.
25345
25346 Once InnoDB is running, the innodb_commit_concurrency must not change
25347 from zero to nonzero. (Bug #42101)
25348
25349 The initial default value is 0, and without this extra initialization,
25350 SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter
25351 to 0, even if it was initially set to nonzero at the command line
25352 or configuration file. */
25353 12027 static void innobase_commit_concurrency_init_default() {
25354 12027 MYSQL_SYSVAR_NAME(commit_concurrency).def_val = innobase_commit_concurrency;
25355 12027 }
25356
25357 /****************************************************************************
25358 DS-MRR implementation
25359 ***************************************************************************/
25360
25361 /**
25362 Multi Range Read interface, DS-MRR calls */
25363 621300 int ha_innobase::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
25364 uint n_ranges, uint mode,
25365 HANDLER_BUFFER *buf) {
25366 621300 m_ds_mrr.init(table);
25367
25368 621325 return (m_ds_mrr.dsmrr_init(seq, seq_init_param, n_ranges, mode, buf));
25369 }
25370
25371 3536410 int ha_innobase::multi_range_read_next(char **range_info) {
25372 3536410 return (m_ds_mrr.dsmrr_next(range_info));
25373 }
25374
25375 603027 ha_rows ha_innobase::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
25376 void *seq_init_param,
25377 uint n_ranges, uint *bufsz,
25378 uint *flags,
25379 Cost_estimate *cost) {
25380 /* See comments in ha_myisam::multi_range_read_info_const */
25381 603027 m_ds_mrr.init(table);
25382
25383 603053 return (m_ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
25384 603109 flags, cost));
25385 }
25386
25387 1302 ha_rows ha_innobase::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
25388 uint *bufsz, uint *flags,
25389 Cost_estimate *cost) {
25390 1302 m_ds_mrr.init(table);
25391
25392 1302 return (m_ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost));
25393 }
25394
25395 /**
25396 Index Condition Pushdown interface implementation */
25397
25398 /** InnoDB index push-down condition check
25399 @return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */
25400 ICP_RESULT
25401 1114114 innobase_index_cond(ha_innobase *h) /*!< in/out: pointer to ha_innobase */
25402 {
25403
1/2
✓ Branch 0 taken 1114114 times.
✗ Branch 1 not taken.
1114114 DBUG_TRACE;
25404
25405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1114114 times.
1114114 assert(h->pushed_idx_cond);
25406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1114114 times.
1114114 assert(h->pushed_idx_cond_keyno != MAX_KEY);
25407
25408
7/8
✓ Branch 0 taken 6853 times.
✓ Branch 1 taken 1107261 times.
✓ Branch 2 taken 6853 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 657 times.
✓ Branch 5 taken 6196 times.
✓ Branch 6 taken 657 times.
✓ Branch 7 taken 1113457 times.
1114114 if (h->end_range && h->compare_key_icp(h->end_range) > 0) {
25409 /* caller should return HA_ERR_END_OF_FILE already */
25410 657 return ICP_OUT_OF_RANGE;
25411 }
25412
25413
3/4
✓ Branch 0 taken 1113457 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1111700 times.
✓ Branch 3 taken 1757 times.
1113457 return h->pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH;
25414 1114114 }
25415
25416 /** Get the computed value by supplying the base column values.
25417 @param[in,out] table the table whose virtual column template to be built */
25418 1 void innobase_init_vc_templ(dict_table_t *table) {
25419
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dict_sys_mutex_enter();
25420
25421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (table->vc_templ != nullptr) {
25422 dict_sys_mutex_exit();
25423
25424 return;
25425 }
25426
25427 1 table->vc_templ =
25428
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY);
25429 1 table->vc_templ->vtempl = nullptr;
25430
25431 1 std::string schema_name;
25432 1 std::string table_name;
25433
25434
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 table->get_table_name(schema_name, table_name);
25435
25436
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 THD *thd = current_thd;
25437
25438 {
25439
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 innodb_session_dict_mutex_guard_t guard(*thd_to_innodb_session(thd));
25440 #ifdef UNIV_DEBUG
25441 bool ret =
25442 #endif /* UNIV_DEBUG */
25443
25444
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 handler::my_prepare_gcolumn_template(
25445 thd, schema_name.c_str(), table_name.c_str(),
25446 &innobase_build_v_templ_callback, static_cast<void *>(table));
25447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 ut_ad(!ret);
25448 1 }
25449
25450
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 dict_sys_mutex_exit();
25451 1 }
25452
25453 /** Change dbname and table name in table->vc_templ.
25454 @param[in,out] table the table whose virtual column template
25455 dbname and tbname to be renamed. */
25456 568 void innobase_rename_vc_templ(dict_table_t *table) {
25457 568 std::string schema_name;
25458 568 std::string table_name;
25459
25460 /* Get table and schema name in system character set. */
25461
1/2
✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
568 table->get_table_name(schema_name, table_name);
25462
25463
1/2
✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
568 table->vc_templ->db_name.assign(schema_name);
25464
1/2
✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
568 table->vc_templ->tb_name.assign(table_name);
25465 568 }
25466
25467 35 dfield_t *innobase_get_field_from_update_vector(dict_foreign_t *foreign,
25468 upd_t *update,
25469 uint32_t col_no) {
25470 35 dict_table_t *parent_table = foreign->referenced_table;
25471 35 dict_index_t *parent_index = foreign->referenced_index;
25472 uint32_t parent_field_no;
25473 uint32_t parent_col_no;
25474 uint32_t child_col_no;
25475
25476
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 11 times.
46 for (uint32_t i = 0; i < foreign->n_fields; i++) {
25477 35 child_col_no = foreign->foreign_index->get_col_no(i);
25478
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 24 times.
35 if (child_col_no != col_no) {
25479 11 continue;
25480 }
25481 24 parent_col_no = parent_index->get_col_no(i);
25482 24 parent_field_no = dict_table_get_nth_col_pos(parent_table, parent_col_no);
25483
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 for (uint32_t j = 0; j < update->n_fields; j++) {
25484 24 upd_field_t *parent_ufield = &update->fields[j];
25485
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (parent_ufield->field_no == parent_field_no) {
25486 24 return (&parent_ufield->new_val);
25487 }
25488 }
25489 }
25490
25491 11 return (nullptr);
25492 }
25493
25494 /** Get the computed value by supplying the base column values.
25495 @param[in,out] row the data row
25496 @param[in] col virtual column
25497 @param[in] index index on the virtual column
25498 @param[in,out] local_heap heap memory for processing large data etc.
25499 @param[in,out] heap memory heap that copies the actual index row
25500 @param[in] ifield index field
25501 @param[in] thd MySQL thread handle
25502 @param[in,out] mysql_table mysql table object
25503 @param[in] old_table during ALTER TABLE, this is the old table
25504 or NULL.
25505 @param[in] parent_update update vector for the parent row
25506 @param[in] foreign foreign key information
25507 @param[in] compress_heap
25508 @return the field filled with computed value, or NULL if just want
25509 to store the value in passed in "my_rec" */
25510 34420 dfield_t *innobase_get_computed_value(
25511 const dtuple_t *row, const dict_v_col_t *col, const dict_index_t *index,
25512 mem_heap_t **local_heap, mem_heap_t *heap, const dict_field_t *ifield,
25513 THD *thd, TABLE *mysql_table, const dict_table_t *old_table,
25514 upd_t *parent_update, dict_foreign_t *foreign, mem_heap_t **compress_heap) {
25515 byte rec_buf1[REC_VERSION_56_MAX_INDEX_COL_LEN];
25516 byte rec_buf2[REC_VERSION_56_MAX_INDEX_COL_LEN];
25517 byte *mysql_rec;
25518 byte *buf;
25519 dfield_t *field;
25520 ulint len;
25521 34420 ulong mv_length = 0;
25522 34420 const char *mv_data_ptr = nullptr;
25523
25524 const page_size_t page_size = (old_table == nullptr)
25525
1/2
✓ Branch 0 taken 7812 times.
✗ Branch 1 not taken.
7812 ? dict_table_page_size(index->table)
25526
3/4
✓ Branch 0 taken 7812 times.
✓ Branch 1 taken 26608 times.
✓ Branch 2 taken 26608 times.
✗ Branch 3 not taken.
34420 : dict_table_page_size(old_table);
25527
25528 34420 const dict_index_t *clust_index = nullptr;
25529
2/2
✓ Branch 0 taken 7812 times.
✓ Branch 1 taken 26608 times.
34420 if (old_table == nullptr) {
25530
1/2
✓ Branch 0 taken 7812 times.
✗ Branch 1 not taken.
7812 clust_index = index->table->first_index();
25531 } else {
25532
1/2
✓ Branch 0 taken 26608 times.
✗ Branch 1 not taken.
26608 clust_index = old_table->first_index();
25533 }
25534
25535 34420 ulint ret = 0;
25536
25537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34420 times.
34420 ut_ad(index->table->vc_templ);
25538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34420 times.
34420 ut_ad(thd != nullptr);
25539
25540 34420 const mysql_row_templ_t *vctempl =
25541 34420 index->table->vc_templ
25542 34420 ->vtempl[index->table->vc_templ->n_col + col->v_pos];
25543
25544
2/2
✓ Branch 0 taken 32961 times.
✓ Branch 1 taken 1459 times.
34420 if (!heap ||
25545
2/2
✓ Branch 0 taken 6421 times.
✓ Branch 1 taken 26540 times.
32961 index->table->vc_templ->rec_len >= REC_VERSION_56_MAX_INDEX_COL_LEN) {
25546
2/2
✓ Branch 0 taken 3379 times.
✓ Branch 1 taken 4501 times.
7880 if (*local_heap == nullptr) {
25547
1/2
✓ Branch 0 taken 3379 times.
✗ Branch 1 not taken.
3379 *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE);
25548 }
25549
25550 mysql_rec = static_cast<byte *>(
25551
1/2
✓ Branch 0 taken 7880 times.
✗ Branch 1 not taken.
7880 mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len));
25552 7880 buf = static_cast<byte *>(
25553
1/2
✓ Branch 0 taken 7880 times.
✗ Branch 1 not taken.
7880 mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len));
25554 } else {
25555 26540 mysql_rec = rec_buf1;
25556 26540 buf = rec_buf2;
25557 }
25558
25559
2/2
✓ Branch 0 taken 38287 times.
✓ Branch 1 taken 34420 times.
72707 for (ulint i = 0; i < col->num_base; i++) {
25560 38287 dict_col_t *base_col = col->base_col[i];
25561 38287 const dfield_t *row_field = nullptr;
25562 38287 uint32_t col_no = base_col->ind;
25563 38287 const mysql_row_templ_t *templ = index->table->vc_templ->vtempl[col_no];
25564 const byte *data;
25565
25566
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 38256 times.
38287 if (parent_update != nullptr) {
25567 row_field =
25568
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 innobase_get_field_from_update_vector(foreign, parent_update, col_no);
25569 }
25570
25571
2/2
✓ Branch 0 taken 38265 times.
✓ Branch 1 taken 22 times.
38287 if (row_field == nullptr) {
25572
1/2
✓ Branch 0 taken 38265 times.
✗ Branch 1 not taken.
38265 row_field = dtuple_get_nth_field(row, col_no);
25573 }
25574
25575 38287 data = static_cast<const byte *>(row_field->data);
25576 38287 len = row_field->len;
25577
25578
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 38152 times.
38287 if (row_field->ext) {
25579
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 128 times.
135 if (*local_heap == nullptr) {
25580
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE);
25581 }
25582
25583 135 data = lob::btr_copy_externally_stored_field(
25584
1/2
✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
135 thd_to_trx(thd), clust_index, &len, nullptr, data, page_size,
25585
2/4
✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 135 times.
✗ Branch 3 not taken.
135 dfield_get_len(row_field), false, *local_heap);
25586 }
25587
25588
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 38218 times.
38287 if (len == UNIV_SQL_NULL) {
25589 69 mysql_rec[templ->mysql_null_byte_offset] |=
25590 69 (byte)templ->mysql_null_bit_mask;
25591 69 memcpy(mysql_rec + templ->mysql_col_offset,
25592 69 static_cast<const byte *>(index->table->vc_templ->default_rec +
25593 69 templ->mysql_col_offset),
25594 69 templ->mysql_col_len);
25595 } else {
25596 38218 row_sel_field_store_in_mysql_format(
25597 38218 mysql_rec + templ->mysql_col_offset, templ, index,
25598
1/2
✓ Branch 0 taken 38218 times.
✗ Branch 1 not taken.
38218 templ->clust_rec_field_no, (const byte *)data, len, compress_heap,
25599 ULINT_UNDEFINED);
25600
25601
2/2
✓ Branch 0 taken 21992 times.
✓ Branch 1 taken 16226 times.
38218 if (templ->mysql_null_bit_mask) {
25602 /* It is a nullable column with a
25603 non-NULL value */
25604 21992 mysql_rec[templ->mysql_null_byte_offset] &=
25605 21992 ~(byte)templ->mysql_null_bit_mask;
25606 }
25607 }
25608 }
25609
25610
1/2
✓ Branch 0 taken 34420 times.
✗ Branch 1 not taken.
34420 field = dtuple_get_nth_v_field(row, col->v_pos);
25611
25612 /* Bitmap for specifying which virtual columns the server
25613 should evaluate */
25614 34420 MY_BITMAP column_map;
25615 my_bitmap_map col_map_storage[bitmap_buffer_size(REC_MAX_N_FIELDS)];
25616
25617
1/2
✓ Branch 0 taken 34420 times.
✗ Branch 1 not taken.
34420 bitmap_init(&column_map, col_map_storage, REC_MAX_N_FIELDS);
25618
25619 /* Specify the column the server should evaluate */
25620 34420 bitmap_set_bit(&column_map, col->m_col.ind);
25621
25622 34420 Temp_table_handle tblhdl;
25623
25624
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 34344 times.
34420 if (mysql_table == nullptr) {
25625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (vctempl->type == DATA_BLOB) {
25626 ulint max_len;
25627
25628 if (vctempl->mysql_col_len - 8 == 1) {
25629 /* This is for TINYBLOB only, which needs
25630 only 1 byte, other BLOBs won't be affected */
25631 max_len = 255;
25632 } else {
25633 max_len = DICT_MAX_FIELD_LEN_BY_FORMAT(index->table) + 1;
25634 }
25635
25636 byte *blob_mem = static_cast<byte *>(mem_heap_alloc(heap, max_len));
25637
25638 row_mysql_store_blob_ref(mysql_rec + vctempl->mysql_col_offset,
25639 vctempl->mysql_col_len, blob_mem, max_len, false,
25640 0, 0, compress_heap);
25641 }
25642
25643 /* open a temporary table handle */
25644
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 mysql_table = tblhdl.open(thd, index->table->vc_templ->db_name.c_str(),
25645 76 index->table->vc_templ->tb_name.c_str());
25646 }
25647
1/2
✓ Branch 0 taken 34420 times.
✗ Branch 1 not taken.
34420 if (mysql_table) {
25648
5/6
✓ Branch 0 taken 25421 times.
✓ Branch 1 taken 8999 times.
✓ Branch 2 taken 25421 times.
✓ Branch 3 taken 8999 times.
✓ Branch 4 taken 34420 times.
✗ Branch 5 not taken.
68840 ret = handler::my_eval_gcolumn_expr(
25649 thd, mysql_table, &column_map, (uchar *)mysql_rec,
25650 34420 (col->m_col.is_multi_value() ? &mv_data_ptr : nullptr),
25651 34420 (col->m_col.is_multi_value() ? &mv_length : nullptr));
25652 } else {
25653 return nullptr;
25654 }
25655
25656
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 34389 times.
34420 if (ret != 0) {
25657 #ifdef INNODB_VIRTUAL_DEBUG
25658 ib::warn(ER_IB_MSG_581) << "Compute virtual column values failed ";
25659 fputs("InnoDB: Cannot compute value for following record ", stderr);
25660 dtuple_print(stderr, row);
25661 #endif /* INNODB_VIRTUAL_DEBUG */
25662 31 return (nullptr);
25663 }
25664
25665
2/2
✓ Branch 0 taken 34287 times.
✓ Branch 1 taken 102 times.
34389 if (vctempl->mysql_null_bit_mask &&
25666 34287 (mysql_rec[vctempl->mysql_null_byte_offset] &
25667
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 34163 times.
34287 vctempl->mysql_null_bit_mask)) {
25668
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 dfield_set_null(field);
25669 124 field->type.prtype |= DATA_VIRTUAL;
25670
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 58 times.
124 if (col->m_col.is_multi_value()) {
25671 66 field->type.prtype |= DATA_MULTI_VALUE;
25672 }
25673 124 return (field);
25674 }
25675
25676
2/2
✓ Branch 0 taken 25327 times.
✓ Branch 1 taken 8938 times.
34265 if (col->m_col.is_multi_value()) {
25677 Field_typed_array *fld;
25678 25327 fld = down_cast<Field_typed_array *>(mysql_table->field[col->m_col.ind]);
25679
1/2
✓ Branch 0 taken 25327 times.
✗ Branch 1 not taken.
25327 json_binary::Value v(json_binary::parse_binary(mv_data_ptr, mv_length));
25680 25327 multi_value_data *value = nullptr;
25681
25682 50654 bool succ = innobase_store_multi_value(
25683
2/4
✓ Branch 0 taken 25327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25327 times.
✗ Branch 3 not taken.
25327 v, value, fld, field, dict_table_is_comp(index->table), heap);
25684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25327 times.
25327 if (!succ) {
25685 ut_error;
25686 }
25687
25688 25327 field->type.prtype |= DATA_MULTI_VALUE;
25689 } else {
25690 8938 row_mysql_store_col_in_innobase_format(
25691 8938 field, buf, true, mysql_rec + vctempl->mysql_col_offset,
25692
2/4
✓ Branch 0 taken 8938 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8938 times.
✗ Branch 3 not taken.
8938 vctempl->mysql_col_len, dict_table_is_comp(index->table), false,
25693 nullptr, 0, nullptr);
25694 }
25695 34265 field->type.prtype |= DATA_VIRTUAL;
25696
25697 34265 ulint max_prefix = col->m_col.max_prefix;
25698
25699
4/4
✓ Branch 0 taken 7372 times.
✓ Branch 1 taken 26893 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 7242 times.
34265 if (max_prefix && ifield &&
25700
2/4
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 130 times.
130 (ifield->prefix_len == 0 || ifield->prefix_len > col->m_col.max_prefix)) {
25701 max_prefix = ifield->prefix_len;
25702 }
25703
25704 /* If this is a prefix index, we only need a portion of the field */
25705
2/2
✓ Branch 0 taken 7372 times.
✓ Branch 1 taken 26893 times.
34265 if (max_prefix) {
25706 14744 len = dtype_get_at_most_n_mbchars(
25707 7372 col->m_col.prtype, col->m_col.mbminmaxlen, max_prefix, field->len,
25708
2/4
✓ Branch 0 taken 7372 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7372 times.
✗ Branch 3 not taken.
7372 static_cast<char *>(dfield_get_data(field)));
25709
1/2
✓ Branch 0 taken 7372 times.
✗ Branch 1 not taken.
7372 dfield_set_len(field, len);
25710 }
25711
25712
7/8
✓ Branch 0 taken 32861 times.
✓ Branch 1 taken 1404 times.
✓ Branch 2 taken 32861 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7534 times.
✓ Branch 5 taken 25327 times.
✓ Branch 6 taken 7534 times.
✓ Branch 7 taken 26731 times.
34265 if (heap != nullptr && !dfield_is_multi_value(field)) {
25713
1/2
✓ Branch 0 taken 7534 times.
✗ Branch 1 not taken.
7534 dfield_dup(field, heap);
25714 }
25715
25716 34265 return (field);
25717 34420 }
25718
25719 /** Attempt to push down an index condition.
25720 @param[in] keyno MySQL key number
25721 @param[in] idx_cond Index condition to be checked
25722 @return idx_cond if pushed; NULL if not pushed */
25723 2538 class Item *ha_innobase::idx_cond_push(uint keyno, class Item *idx_cond) {
25724
1/2
✓ Branch 0 taken 2538 times.
✗ Branch 1 not taken.
2538 DBUG_TRACE;
25725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2538 times.
2538 assert(keyno != MAX_KEY);
25726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2538 times.
2538 assert(idx_cond != nullptr);
25727
25728 2538 pushed_idx_cond = idx_cond;
25729 2538 pushed_idx_cond_keyno = keyno;
25730 2538 in_range_check_pushed_down = true;
25731 /* We will evaluate the condition entirely */
25732 2538 return nullptr;
25733 2538 }
25734
25735 /** Find out if a Record_buffer is wanted by this handler, and what is the
25736 maximum buffer size the handler wants.
25737
25738 @param[out] max_rows gets set to the maximum number of records to allocate
25739 space for in the buffer
25740 @retval true if the handler wants a buffer
25741 @retval false if the handler does not want a buffer */
25742 555976 bool ha_innobase::is_record_buffer_wanted(ha_rows *const max_rows) const {
25743 /* If the scan won't be able to utilize the record buffer, return that
25744 we don't want one. The decision on whether to use a buffer is taken in
25745 row_search_mvcc(), look for the comment that starts with "Decide
25746 whether to prefetch extra rows." Let's do the same check here. */
25747
25748
2/2
✓ Branch 0 taken 374908 times.
✓ Branch 1 taken 181073 times.
555976 if (!m_prebuilt->can_prefetch_records()) {
25749 374908 *max_rows = 0;
25750 374908 return false;
25751 }
25752
25753 /* Limit the number of rows in the buffer to 100 for now. We may want
25754 to fine-tune this later, possibly taking record size and page size into
25755 account. The optimizer might allocate an even smaller buffer if it
25756 thinks a smaller number of rows will be fetched. */
25757 181073 *max_rows = 100;
25758 181073 return true;
25759 }
25760
25761 /** Return max limits for a single set of multi-valued keys
25762 @param[out] num_keys number of keys to store
25763 @param[out] keys_length total length of keys, bytes
25764 */
25765 27978 void ha_innobase::mv_key_capacity(uint *num_keys, size_t *keys_length) const {
25766 /* The limit of multi-value should be checked against undo page size,
25767 because a record length can not be longer than an undo page size.
25768 Actually, it should not be longer than half of a page size, but this
25769 can be checked for the full record.
25770
25771 The problem is, even if the number of multi-value fields are known,
25772 the actual number of multiple values per field are not known until
25773 the record itself gets inserted. So it's impossible to estimate the
25774 accurate max number of multiple values. Meanwhile, since other fields
25775 are not known in advance, so it's also impossible to estimate the
25776 accurate total key length.
25777
25778 Therefore, only the best effort can be done in this function.
25779 That is the estimation will be based on the INSERT to the table.
25780 And excluding all must have space, the left length is regarded
25781 as the keys_length. And the number of the keys would be got by
25782 keys_length / min(multi-value fields' length). Note if it is a
25783 variable length field, then it's data length is regarded as 1.
25784
25785 Furthermore, to make the calculation as simple as possible, some
25786 space cost would be ignored. This should not be a big deal, since
25787 the whole estimation is only a rough one.
25788
25789 So it's the greedy estimation which will try to give a most relaxed
25790 restriction on the table, to allow insert and update go as more as
25791 possible. The DB_UNDO_RECORD_TOO_BIG error would be raised if the
25792 actual user record exceeds the undo page size. */
25793
25794 27978 size_t free_space = trx_undo_max_free_space();
25795
25796 /* PK always takes place in log page, take that into account */
25797 27978 uint pk = table->s->primary_key;
25798
2/2
✓ Branch 0 taken 17555 times.
✓ Branch 1 taken 10423 times.
27978 if (pk != MAX_KEY) {
25799 17555 free_space -= table->s->key_info[pk].key_length;
25800 } else {
25801 /* Deduct default InnoDB's PK length */
25802 10423 free_space -= DATA_ROW_ID_LEN;
25803 }
25804
25805 /* Maybe the space for any normal virtual columns etc. should be
25806 considered here, however, no details can be know at this time point,
25807 so just ignore them all */
25808
25809 /* Find out the minimum key length so to get the maximum number
25810 of keys */
25811 27978 uint16_t min_mv_key_length = std::numeric_limits<uint16_t>::max();
25812
25813
2/2
✓ Branch 0 taken 89128 times.
✓ Branch 1 taken 26575 times.
115703 for (uint16_t i = 0; i < table->s->fields; ++i) {
25814 89128 Field *field = table->field[i];
25815
2/2
✓ Branch 0 taken 60874 times.
✓ Branch 1 taken 28254 times.
89128 if (!innobase_is_multi_value_fld(field)) {
25816 60874 continue;
25817 }
25818
25819 /* In case of variable length type, assume the minimum length of data,
25820 to make a maximum estimation of keys and allow users to insert as
25821 many keys as possible, under the constraint of total key length. */
25822
2/2
✓ Branch 0 taken 1403 times.
✓ Branch 1 taken 26851 times.
28254 if (field->type() == MYSQL_TYPE_VARCHAR) {
25823 1403 min_mv_key_length = 1;
25824 1403 break;
25825 }
25826
25827
2/2
✓ Branch 0 taken 26760 times.
✓ Branch 1 taken 91 times.
26851 if (min_mv_key_length > field->key_length()) {
25828 26760 min_mv_key_length = field->key_length();
25829 }
25830 }
25831
25832 27978 *keys_length = Multi_value_logger::get_keys_capacity(
25833 static_cast<uint32_t>(free_space), min_mv_key_length, num_keys);
25834 27978 }
25835
25836 /** Use this when the args are passed to the format string from
25837 messages_to_clients.txt directly as is.
25838
25839 Push a warning message to the client, it is a wrapper around:
25840
25841 void push_warning_printf(
25842 THD *thd, Sql_condition::enum_condition_level level,
25843 uint code, const char *format, ...);
25844 */
25845 3042 void ib_senderrf(THD *thd, /*!< in/out: session */
25846 ib_log_level_t level, /*!< in: warning level */
25847 uint32_t code, /*!< MySQL error code */
25848 ...) /*!< Args */
25849 {
25850 va_list args;
25851 3042 char *str = nullptr;
25852
1/2
✓ Branch 0 taken 3042 times.
✗ Branch 1 not taken.
3042 const char *format = innobase_get_err_msg(code);
25853
25854 /* If the caller wants to push a message to the client then
25855 the caller must pass a valid session handle. */
25856
25857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
3042 ut_a(thd != nullptr);
25858
25859 /* The error code must exist in the messages_to_clients.txt file. */
25860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
3042 ut_a(format != nullptr);
25861
25862 3042 va_start(args, code);
25863
25864 #ifdef _WIN32
25865 int size = _vscprintf(format, args) + 1;
25866 if (size > 0) {
25867 str = static_cast<char *>(malloc(size));
25868 }
25869 if (str == NULL) {
25870 va_end(args);
25871 return; /* Watch for Out-Of-Memory */
25872 }
25873 str[size - 1] = 0x0;
25874 vsnprintf(str, size, format, args);
25875 #elif HAVE_VASPRINTF
25876 int ret;
25877 3042 ret = vasprintf(&str, format, args);
25878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
3042 if (ret < 0) {
25879 va_end(args);
25880 return; /* Watch for Out-Of-Memory */
25881 }
25882 #else
25883 /* Use a fixed length string. */
25884 str = static_cast<char *>(malloc(BUFSIZ));
25885 if (str == NULL) {
25886 va_end(args);
25887 return; /* Watch for Out-Of-Memory */
25888 }
25889 vsnprintf(str, BUFSIZ, format, args);
25890 #endif /* _WIN32 */
25891
25892 Sql_condition::enum_severity_level l;
25893
25894 3042 l = Sql_condition::SL_NOTE;
25895
25896
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2380 times.
✓ Branch 2 taken 662 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3042 switch (level) {
25897 case IB_LOG_LEVEL_INFO:
25898 break;
25899 2380 case IB_LOG_LEVEL_WARN:
25900 2380 l = Sql_condition::SL_WARNING;
25901 2380 break;
25902 662 case IB_LOG_LEVEL_ERROR:
25903 /* We can't use push_warning_printf(), it is a hard error. */
25904
1/2
✓ Branch 0 taken 662 times.
✗ Branch 1 not taken.
662 my_printf_error(code, "%s", MYF(0), str);
25905 662 break;
25906 case IB_LOG_LEVEL_FATAL:
25907 l = Sql_condition::SEVERITY_END;
25908 break;
25909 #ifdef UNIV_HOTBACKUP
25910 default:
25911 break;
25912 #endif /* UNIV_HOTBACKUP */
25913 }
25914
25915
2/2
✓ Branch 0 taken 2380 times.
✓ Branch 1 taken 662 times.
3042 if (level != IB_LOG_LEVEL_ERROR) {
25916
1/2
✓ Branch 0 taken 2380 times.
✗ Branch 1 not taken.
2380 push_warning_printf(thd, l, code, "InnoDB: %s", str);
25917 }
25918
25919 3042 va_end(args);
25920 3042 free(str);
25921
25922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
3042 if (level == IB_LOG_LEVEL_FATAL) {
25923 ut_error;
25924 }
25925 }
25926
25927 /** Use this when the args are first converted to a formatted string and then
25928 passed to the format string from messages_to_clients.txt. The error message
25929 format must be: "Some string ... %s".
25930
25931 Push a warning message to the client, it is a wrapper around:
25932
25933 void push_warning_printf(
25934 THD *thd, Sql_condition::enum_condition_level level,
25935 uint code, const char *format, ...);
25936 */
25937 378 void ib_errf(THD *thd, /*!< in/out: session */
25938 ib_log_level_t level, /*!< in: warning level */
25939 uint32_t code, /*!< MySQL error code */
25940 const char *format, /*!< printf format */
25941 ...) /*!< Args */
25942 {
25943 378 char *str = nullptr;
25944 va_list args;
25945
25946 /* If the caller wants to push a message to the client then
25947 the caller must pass a valid session handle. */
25948
25949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
378 ut_a(thd != nullptr);
25950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
378 ut_a(format != nullptr);
25951
25952 378 va_start(args, format);
25953
25954 #ifdef _WIN32
25955 int size = _vscprintf(format, args) + 1;
25956 if (size > 0) {
25957 str = static_cast<char *>(malloc(size));
25958 }
25959 if (str == NULL) {
25960 va_end(args);
25961 return; /* Watch for Out-Of-Memory */
25962 }
25963 str[size - 1] = 0x0;
25964 vsnprintf(str, size, format, args);
25965 #elif HAVE_VASPRINTF
25966 int ret;
25967 378 ret = vasprintf(&str, format, args);
25968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
378 if (ret < 0) {
25969 va_end(args);
25970 return; /* Watch for Out-Of-Memory */
25971 }
25972 #else
25973 /* Use a fixed length string. */
25974 str = static_cast<char *>(malloc(BUFSIZ));
25975 if (str == NULL) {
25976 va_end(args);
25977 return; /* Watch for Out-Of-Memory */
25978 }
25979 vsnprintf(str, BUFSIZ, format, args);
25980 #endif /* _WIN32 */
25981
25982
1/2
✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
378 ib_senderrf(thd, level, code, str);
25983
25984 378 va_end(args);
25985 378 free(str);
25986 }
25987 #endif /* !UNIV_HOTBACKUP */
25988
25989 /* Keep the first 16 characters as-is, since the url is sometimes used
25990 as an offset from this.*/
25991 const char *TROUBLESHOOTING_MSG = "Please refer to " REFMAN
25992 "innodb-troubleshooting.html"
25993 " for how to resolve the issue.";
25994
25995 const char *TROUBLESHOOT_DATADICT_MSG = "Please refer to " REFMAN
25996 "innodb-troubleshooting-datadict.html"
25997 " for how to resolve the issue.";
25998
25999 const char *BUG_REPORT_MSG =
26000 "Submit a detailed bug report to http://bugs.mysql.com";
26001
26002 const char *FORCE_RECOVERY_MSG = "Please refer to " REFMAN
26003 "forcing-innodb-recovery.html"
26004 " for information about forcing recovery.";
26005
26006 const char *ERROR_CREATING_MSG =
26007 "Please refer to " REFMAN "error-creating-innodb.html";
26008
26009 const char *OPERATING_SYSTEM_ERROR_MSG =
26010 "Refer to your operating system documentation for operating"
26011 " system error code information.";
26012
26013 const char *FOREIGN_KEY_CONSTRAINTS_MSG =
26014 "Please refer to " REFMAN
26015 "create-table-foreign-keys.html"
26016 " for correct foreign key definition.";
26017
26018 const char *INNODB_PARAMETERS_MSG =
26019 "Please refer to " REFMAN "innodb-parameters.html";
26020
26021 #ifndef UNIV_HOTBACKUP
26022 /**********************************************************************
26023 Converts an identifier from my_charset_filename to UTF-8 charset.
26024 @return result string length, as returned by strconvert() */
26025 453 uint innobase_convert_to_filename_charset(
26026 char *to, /* out: converted identifier */
26027 const char *from, /* in: identifier to convert */
26028 ulint len) /* in: length of 'to', in bytes */
26029 {
26030 uint errors;
26031 453 CHARSET_INFO *cs_to = &my_charset_filename;
26032 453 CHARSET_INFO *cs_from = system_charset_info;
26033
26034 return (static_cast<uint>(
26035
1/2
✓ Branch 0 taken 453 times.
✗ Branch 1 not taken.
453 strconvert(cs_from, from, cs_to, to, static_cast<size_t>(len), &errors)));
26036 }
26037
26038 /**********************************************************************
26039 Converts an identifier from my_charset_filename to UTF-8 charset.
26040 @return result string length, as returned by strconvert() */
26041 49 uint innobase_convert_to_system_charset(
26042 char *to, /* out: converted identifier */
26043 const char *from, /* in: identifier to convert */
26044 ulint len, /* in: length of 'to', in bytes */
26045 uint *errors) /* out: error return */
26046 {
26047 49 CHARSET_INFO *cs1 = &my_charset_filename;
26048 49 CHARSET_INFO *cs2 = system_charset_info;
26049
26050 return (static_cast<uint>(
26051 49 strconvert(cs1, from, cs2, to, static_cast<size_t>(len), errors)));
26052 }
26053
26054 /**********************************************************************
26055 Issue a warning that the row is too big. */
26056 41 void ib_warn_row_too_big(const dict_table_t *table) {
26057 /* If prefix is true then a 768-byte prefix is stored
26058 locally for BLOB fields. */
26059 41 const bool prefix = !dict_table_has_atomic_blobs(table);
26060
26061 const ulint free_space =
26062 41 page_get_free_space_of_empty(table->flags & DICT_TF_COMPACT) / 2;
26063
26064 41 THD *thd = current_thd;
26065
26066
4/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 21 times.
41 push_warning_printf(
26067 thd, Sql_condition::SL_WARNING, HA_ERR_TOO_BIG_ROW,
26068 "Row size too large (> %lu). Changing some columns to TEXT"
26069 " or BLOB %smay help. In current row format, BLOB prefix of"
26070 " %d bytes is stored inline.",
26071 free_space,
26072 prefix ? "or using ROW_FORMAT=DYNAMIC or"
26073 " ROW_FORMAT=COMPRESSED "
26074 : "",
26075 prefix ? DICT_MAX_FIXED_COL_LEN : 0);
26076 41 }
26077
26078 /** Constructs fake dict_col_t describing column for foreign key type
26079 compatibility check from column description in Ha_fk_column_type form.
26080
26081 @note dict_col_t which is produced by this call is not valid for general
26082 purposes.
26083 @param[out] col dict_col_t filled by this function
26084 @param[in] fk_col_type foreign key type information */
26085 678106 static void innodb_fill_fake_column_struct(
26086 dict_col_t *col, const Ha_fk_column_type *fk_col_type) {
26087 ulint unsigned_type;
26088 ulint binary_type;
26089 ulint charset_no;
26090
26091 1356212 ulint mtype = get_innobase_type_from_mysql_dd_type(
26092 678106 &unsigned_type, &binary_type, &charset_no, fk_col_type->type,
26093
1/2
✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
678106 fk_col_type->field_charset, fk_col_type->is_unsigned);
26094
26095 /* Fake prtype only contains info which is relevant for foreign key
26096 type compatibility check, especially the info used in cmp_cols_are_equal. */
26097 ulint fake_prtype =
26098
1/2
✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
678106 dtype_form_prtype(unsigned_type | binary_type, charset_no);
26099
26100 1356212 ulint col_len = calc_pack_length(
26101 678106 fk_col_type->type, fk_col_type->char_length, fk_col_type->elements_count,
26102 /* InnoDB always treats BIT as char. */
26103
1/2
✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
678106 true, fk_col_type->numeric_scale, fk_col_type->is_unsigned);
26104
26105
1/2
✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
678106 dict_mem_fill_column_struct(col, 0 /* fake col_pos */, mtype, fake_prtype,
26106 col_len, true, UINT32_UNDEFINED, 0, 0);
26107 678106 }
26108
26109 /** Check if types of child and parent columns in foreign key are compatible.
26110
26111 @param[in] child_column_type Child column type description.
26112 @param[in] parent_column_type Parent column type description.
26113 @param[in] check_charsets Indicates whether we need to check
26114 that charsets of string columns
26115 match. Which is true in most cases.
26116
26117 @return True if types are compatible, False if not. */
26118 339053 static bool innodb_check_fk_column_compat(
26119 const Ha_fk_column_type *child_column_type,
26120 const Ha_fk_column_type *parent_column_type, bool check_charsets) {
26121 339053 dict_col_t dict_child_col, dict_parent_col;
26122
26123
1/2
✓ Branch 0 taken 339053 times.
✗ Branch 1 not taken.
339053 innodb_fill_fake_column_struct(&dict_child_col, child_column_type);
26124
1/2
✓ Branch 0 taken 339053 times.
✗ Branch 1 not taken.
339053 innodb_fill_fake_column_struct(&dict_parent_col, parent_column_type);
26125
26126 return (
26127
1/2
✓ Branch 0 taken 339053 times.
✗ Branch 1 not taken.
678106 cmp_cols_are_equal(&dict_child_col, &dict_parent_col, check_charsets));
26128 }
26129
26130 18536 static bool innobase_check_reserved_file_name(handlerton *, const char *name) {
26131 18536 CHARSET_INFO *ci = system_charset_info;
26132 18536 size_t logname_size = strlen(log_pre_8_0_30::FILE_BASE_NAME);
26133
26134 /* Name is smaller than reserved name */
26135
2/2
✓ Branch 0 taken 17177 times.
✓ Branch 1 taken 1359 times.
18536 if (strlen(name) < logname_size) {
26136 17177 return (false);
26137 }
26138 /* Do case insensitive comparison for name. */
26139
1/2
✓ Branch 0 taken 1405 times.
✗ Branch 1 not taken.
1405 for (uint i = 0; i < logname_size; i++) {
26140
3/6
✓ Branch 0 taken 1405 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1405 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1405 times.
1405 ut_ad(!my_isalpha(ci, log_pre_8_0_30::FILE_BASE_NAME[i]) ||
26141 my_islower(ci, log_pre_8_0_30::FILE_BASE_NAME[i]));
26142
26143
2/2
✓ Branch 0 taken 1359 times.
✓ Branch 1 taken 46 times.
1405 if (my_tolower(ci, name[i]) != log_pre_8_0_30::FILE_BASE_NAME[i]) {
26144 1359 return (false);
26145 }
26146 }
26147 return (true);
26148 }
26149 #endif /* !UNIV_HOTBACKUP */
26150